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::{binder, symbols::Name};
6use rowan::TextSize;
7use squawk_syntax::SyntaxNode;
8use squawk_syntax::{
9 SyntaxKind,
10 ast::{self, AstNode},
11};
12
13pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
14 let token = token_from_offset(file, offset)?;
15 let parent = token.parent()?;
16
17 let root = file.syntax();
18 let binder = binder::bind(file);
19
20 if token.kind() == SyntaxKind::STAR {
21 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone())
22 && field_expr.star_token().is_some()
23 && let Some(result) = hover_qualified_star(root, &field_expr, &binder)
24 {
25 return Some(result);
26 }
27
28 if let Some(arg_list) = ast::ArgList::cast(parent.clone())
29 && let Some(result) = hover_unqualified_star_in_arg_list(root, &arg_list, &binder)
30 {
31 return Some(result);
32 }
33
34 if let Some(target) = ast::Target::cast(parent.clone())
35 && target.star_token().is_some()
36 && let Some(result) = hover_unqualified_star(root, &target, &binder)
37 {
38 return Some(result);
39 }
40 }
41
42 if let Some(name_ref) = ast::NameRef::cast(parent.clone()) {
43 let context = classify_name_ref(&name_ref)?;
44 match context {
45 NameRefClass::CreateIndexColumn
46 | NameRefClass::InsertColumn
47 | NameRefClass::DeleteWhereColumn
48 | NameRefClass::UpdateWhereColumn
49 | NameRefClass::UpdateSetColumn
50 | NameRefClass::UpdateReturningColumn
51 | NameRefClass::InsertReturningColumn
52 | NameRefClass::DeleteReturningColumn
53 | NameRefClass::MergeReturningColumn
54 | NameRefClass::MergeWhenColumn
55 | NameRefClass::MergeOnColumn
56 | NameRefClass::CheckConstraintColumn
57 | NameRefClass::GeneratedColumn
58 | NameRefClass::UniqueConstraintColumn
59 | NameRefClass::PrimaryKeyConstraintColumn
60 | NameRefClass::NotNullConstraintColumn
61 | NameRefClass::ExcludeConstraintColumn
62 | NameRefClass::PartitionByColumn
63 | NameRefClass::JoinUsingColumn
64 | NameRefClass::ForeignKeyColumn
65 | NameRefClass::ForeignKeyLocalColumn
66 | NameRefClass::SequenceOwnedByColumn
67 | NameRefClass::AlterTableColumn
68 | NameRefClass::AlterTableDropColumn => {
69 return hover_column(root, &name_ref, &binder);
70 }
71 NameRefClass::TypeReference | NameRefClass::DropType => {
72 return hover_type(root, &name_ref, &binder);
73 }
74 NameRefClass::CompositeTypeField => {
75 return hover_composite_type_field(root, &name_ref, &binder);
76 }
77 NameRefClass::SelectColumn | NameRefClass::SelectQualifiedColumn => {
78 if let Some(result) = hover_column(root, &name_ref, &binder) {
80 return Some(result);
81 }
82 if let Some(result) = hover_function(root, &name_ref, &binder) {
84 return Some(result);
85 }
86 return hover_table(root, &name_ref, &binder);
88 }
89 NameRefClass::Table
90 | NameRefClass::DropTable
91 | NameRefClass::DropView
92 | NameRefClass::DropMaterializedView
93 | NameRefClass::CreateIndex
94 | NameRefClass::InsertTable
95 | NameRefClass::InsertQualifiedColumnTable
96 | NameRefClass::DeleteTable
97 | NameRefClass::DeleteQualifiedColumnTable
98 | NameRefClass::DeleteUsingTable
99 | NameRefClass::MergeUsingTable
100 | NameRefClass::UpdateTable
101 | NameRefClass::SelectFromTable
102 | NameRefClass::UpdateFromTable
103 | NameRefClass::SelectQualifiedColumnTable
104 | NameRefClass::UpdateSetQualifiedColumnTable
105 | NameRefClass::MergeQualifiedColumnTable
106 | NameRefClass::UpdateReturningQualifiedColumnTable
107 | NameRefClass::InsertReturningQualifiedColumnTable
108 | NameRefClass::DeleteReturningQualifiedColumnTable
109 | NameRefClass::MergeReturningQualifiedColumnTable
110 | NameRefClass::MergeTable
111 | NameRefClass::ForeignKeyTable
112 | NameRefClass::LikeTable
113 | NameRefClass::InheritsTable
114 | NameRefClass::PartitionOfTable
115 | NameRefClass::TruncateTable
116 | NameRefClass::LockTable
117 | NameRefClass::VacuumTable
118 | NameRefClass::AlterTable
119 | NameRefClass::ReindexTable
120 | NameRefClass::RefreshMaterializedView => {
121 return hover_table(root, &name_ref, &binder);
122 }
123 NameRefClass::DropSequence => return hover_sequence(root, &name_ref, &binder),
124 NameRefClass::DropDatabase
125 | NameRefClass::ReindexDatabase
126 | NameRefClass::ReindexSystem => return hover_database(root, &name_ref, &binder),
127 NameRefClass::DropServer
128 | NameRefClass::AlterServer
129 | NameRefClass::CreateServer
130 | NameRefClass::ForeignTableServerName => {
131 return hover_server(root, &name_ref, &binder);
132 }
133 NameRefClass::Tablespace => return hover_tablespace(root, &name_ref, &binder),
134 NameRefClass::DropIndex | NameRefClass::ReindexIndex => {
135 return hover_index(root, &name_ref, &binder);
136 }
137 NameRefClass::DropFunction | NameRefClass::DefaultConstraintFunctionCall => {
138 return hover_function(root, &name_ref, &binder);
139 }
140 NameRefClass::DropAggregate => return hover_aggregate(root, &name_ref, &binder),
141 NameRefClass::DropProcedure | NameRefClass::CallProcedure => {
142 return hover_procedure(root, &name_ref, &binder);
143 }
144 NameRefClass::DropRoutine => return hover_routine(root, &name_ref, &binder),
145 NameRefClass::SelectFunctionCall => {
146 if let Some(result) = hover_function(root, &name_ref, &binder) {
149 return Some(result);
150 }
151 return hover_column(root, &name_ref, &binder);
152 }
153 NameRefClass::SchemaQualifier
154 | NameRefClass::DropSchema
155 | NameRefClass::CreateSchema
156 | NameRefClass::ReindexSchema => {
157 return hover_schema(root, &name_ref, &binder);
158 }
159 }
160 }
161
162 if let Some(name) = ast::Name::cast(parent) {
163 let context = classify_name(&name)?;
164 match context {
165 NameClass::ColumnDefinition {
166 create_table,
167 column,
168 } => return hover_column_definition(&create_table, &column, &binder),
169 NameClass::CreateTable(create_table) => {
170 return format_create_table(&create_table, &binder);
171 }
172 NameClass::WithTable(with_table) => return format_with_table(&with_table),
173 NameClass::CreateIndex(create_index) => {
174 return format_create_index(&create_index, &binder);
175 }
176 NameClass::CreateSequence(create_sequence) => {
177 return format_create_sequence(&create_sequence, &binder);
178 }
179 NameClass::CreateTablespace(create_tablespace) => {
180 return format_create_tablespace(&create_tablespace);
181 }
182 NameClass::CreateDatabase(create_database) => {
183 return format_create_database(&create_database);
184 }
185 NameClass::CreateServer(create_server) => {
186 return format_create_server(&create_server);
187 }
188 NameClass::CreateType(create_type) => {
189 return format_create_type(&create_type, &binder);
190 }
191 NameClass::CreateFunction(create_function) => {
192 return format_create_function(&create_function, &binder);
193 }
194 NameClass::CreateAggregate(create_aggregate) => {
195 return format_create_aggregate(&create_aggregate, &binder);
196 }
197 NameClass::CreateProcedure(create_procedure) => {
198 return format_create_procedure(&create_procedure, &binder);
199 }
200 NameClass::CreateSchema(create_schema) => {
201 return format_create_schema(&create_schema);
202 }
203 NameClass::ViewColumnList { create_view, name } => {
204 return format_view_column(&create_view, Name::from_node(&name), &binder);
205 }
206 NameClass::CreateView(create_view) => {
207 return format_create_view(&create_view, &binder);
208 }
209 }
210 }
211
212 None
213}
214
215struct ColumnHover {}
216impl ColumnHover {
217 fn table_column(table_name: &str, column_name: &str) -> String {
218 format!("column {table_name}.{column_name}")
219 }
220 fn schema_table_column_type(
221 schema: &str,
222 table_name: &str,
223 column_name: &str,
224 ty: &str,
225 ) -> String {
226 format!("column {schema}.{table_name}.{column_name} {ty}")
227 }
228 fn schema_table_column(schema: &str, table_name: &str, column_name: &str) -> String {
229 format!("column {schema}.{table_name}.{column_name}")
230 }
231}
232
233fn hover_column(
234 root: &SyntaxNode,
235 name_ref: &ast::NameRef,
236 binder: &binder::Binder,
237) -> Option<String> {
238 let column_ptrs = resolve::resolve_name_ref(binder, root, name_ref)?;
239
240 let results: Vec<String> = column_ptrs
241 .iter()
242 .filter_map(|column_ptr| {
243 let column_name_node = column_ptr.to_node(root);
244 format_hover_for_column_node(binder, &column_name_node, name_ref)
245 })
246 .collect();
247
248 if results.is_empty() {
249 return None;
250 }
251
252 Some(results.join("\n"))
253}
254
255fn format_hover_for_column_node(
256 binder: &binder::Binder,
257 column_name_node: &squawk_syntax::SyntaxNode,
258 name_ref: &ast::NameRef,
259) -> Option<String> {
260 for a in column_name_node.ancestors() {
261 if let Some(with_table) = ast::WithTable::cast(a.clone()) {
262 let cte_name = with_table.name()?;
263 let column_name = if column_name_node
264 .ancestors()
265 .any(|a| ast::Values::can_cast(a.kind()))
266 {
267 Name::from_node(name_ref)
268 } else {
269 Name::from_string(column_name_node.text().to_string())
270 };
271 let table_name = Name::from_node(&cte_name);
272 return Some(ColumnHover::table_column(
273 &table_name.to_string(),
274 &column_name.to_string(),
275 ));
276 }
277 if ast::ParenSelect::can_cast(a.kind())
278 && let Some(field_expr) = name_ref.syntax().parent().and_then(ast::FieldExpr::cast)
279 && let Some(base) = field_expr.base()
280 && let ast::Expr::NameRef(table_name_ref) = base
281 {
282 let table_name = Name::from_node(&table_name_ref);
283 let column_name = Name::from_string(column_name_node.text().to_string());
284 return Some(ColumnHover::table_column(
285 &table_name.to_string(),
286 &column_name.to_string(),
287 ));
288 }
289
290 if let Some(create_view) = ast::CreateView::cast(a.clone())
294 && let Some(column_name) =
295 ast::Name::cast(column_name_node.clone()).map(|name| Name::from_node(&name))
296 {
297 return format_view_column(&create_view, column_name, binder);
298 }
299 }
300
301 let column = column_name_node.ancestors().find_map(ast::Column::cast)?;
302 let column_name = column.name()?;
303 let ty = column.ty()?;
304
305 let create_table = column
306 .syntax()
307 .ancestors()
308 .find_map(ast::CreateTableLike::cast)?;
309 let path = create_table.path()?;
310 let (schema, table_name) = resolve::resolve_table_info(binder, &path)?;
311
312 let schema = schema.to_string();
313 let column_name = Name::from_node(&column_name);
314 let ty = &ty.syntax().text().to_string();
315 Some(ColumnHover::schema_table_column_type(
316 &schema,
317 &table_name,
318 &column_name.to_string(),
319 ty,
320 ))
321}
322
323fn hover_composite_type_field(
324 root: &SyntaxNode,
325 name_ref: &ast::NameRef,
326 binder: &binder::Binder,
327) -> Option<String> {
328 let field_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
329 .into_iter()
330 .next()?;
331 let field_name_node = field_ptr.to_node(root);
332
333 let column = field_name_node.ancestors().find_map(ast::Column::cast)?;
334 let field_name = column.name()?.syntax().text().to_string();
335 let ty = column.ty()?;
336
337 let create_type = column
338 .syntax()
339 .ancestors()
340 .find_map(ast::CreateType::cast)?;
341 let type_path = create_type.path()?;
342 let (schema, type_name) = resolve::resolve_type_info(binder, &type_path)?;
343
344 Some(format!(
345 "field {}.{}.{} {}",
346 schema,
347 type_name,
348 field_name,
349 ty.syntax().text()
350 ))
351}
352
353fn hover_column_definition(
354 create_table: &impl ast::HasCreateTable,
355 column: &ast::Column,
356 binder: &binder::Binder,
357) -> Option<String> {
358 let column_name = column.name()?.syntax().text().to_string();
359 let ty = column.ty()?;
360 let path = create_table.path()?;
361 let (schema, table_name) = resolve::resolve_table_info(binder, &path)?;
362 let ty = ty.syntax().text().to_string();
363 Some(ColumnHover::schema_table_column_type(
364 &schema.to_string(),
365 &table_name,
366 &column_name,
367 &ty,
368 ))
369}
370
371fn hover_table(
372 root: &SyntaxNode,
373 name_ref: &ast::NameRef,
374 binder: &binder::Binder,
375) -> Option<String> {
376 if let Some(result) = hover_subquery_table(name_ref) {
377 return Some(result);
378 }
379
380 let table_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
381 .into_iter()
382 .next()?;
383
384 hover_table_from_ptr(root, &table_ptr, binder)
385}
386
387fn hover_table_from_ptr(
388 root: &SyntaxNode,
389 table_ptr: &squawk_syntax::SyntaxNodePtr,
390 binder: &binder::Binder,
391) -> Option<String> {
392 let table_name_node = table_ptr.to_node(root);
393
394 match resolve::find_table_source(&table_name_node)? {
395 resolve::TableSource::WithTable(with_table) => format_with_table(&with_table),
396 resolve::TableSource::CreateView(create_view) => format_create_view(&create_view, binder),
397 resolve::TableSource::CreateMaterializedView(create_materialized_view) => {
398 format_create_materialized_view(&create_materialized_view, binder)
399 }
400 resolve::TableSource::CreateTable(create_table) => {
401 format_create_table(&create_table, binder)
402 }
403 }
404}
405
406fn hover_qualified_star(
407 root: &SyntaxNode,
408 field_expr: &ast::FieldExpr,
409 binder: &binder::Binder,
410) -> Option<String> {
411 let table_ptr = resolve::resolve_qualified_star_table(binder, field_expr)?;
412 hover_qualified_star_columns(root, &table_ptr, binder)
413}
414
415fn hover_unqualified_star(
416 root: &SyntaxNode,
417 target: &ast::Target,
418 binder: &binder::Binder,
419) -> Option<String> {
420 let table_ptrs = resolve::resolve_unqualified_star_tables(binder, target)?;
421 let mut results = vec![];
422 for table_ptr in table_ptrs {
423 if let Some(columns) = hover_qualified_star_columns(root, &table_ptr, binder) {
424 results.push(columns);
425 }
426 }
427
428 if results.is_empty() {
429 return None;
430 }
431
432 Some(results.join("\n"))
433}
434
435fn hover_unqualified_star_in_arg_list(
436 root: &SyntaxNode,
437 arg_list: &ast::ArgList,
438 binder: &binder::Binder,
439) -> Option<String> {
440 let table_ptrs = resolve::resolve_unqualified_star_tables_in_arg_list(binder, arg_list)?;
441 let mut results = vec![];
442 for table_ptr in table_ptrs {
443 if let Some(columns) = hover_qualified_star_columns(root, &table_ptr, binder) {
444 results.push(columns);
445 }
446 }
447
448 if results.is_empty() {
449 return None;
450 }
451
452 Some(results.join("\n"))
453}
454
455fn hover_subquery_table(name_ref: &ast::NameRef) -> Option<String> {
456 let select = name_ref.syntax().ancestors().find_map(ast::Select::cast)?;
457 let from_clause = select.from_clause()?;
458 let qualifier = Name::from_node(name_ref);
459 let from_item = resolve::find_from_item_in_from_clause(&from_clause, &qualifier)?;
460 let paren_select = from_item.paren_select()?;
461 format_subquery_table(name_ref, &paren_select)
462}
463
464fn format_subquery_table(
465 name_ref: &ast::NameRef,
466 paren_select: &ast::ParenSelect,
467) -> Option<String> {
468 let name = name_ref.syntax().text().to_string();
469 let query = paren_select.syntax().text().to_string();
470 Some(format!("subquery {} as {}", name, query))
471}
472
473fn hover_qualified_star_columns(
474 root: &SyntaxNode,
475 table_ptr: &squawk_syntax::SyntaxNodePtr,
476 binder: &binder::Binder,
477) -> Option<String> {
478 let table_name_node = table_ptr.to_node(root);
479
480 if let Some(paren_select) = ast::ParenSelect::cast(table_name_node.clone()) {
481 return hover_qualified_star_columns_from_subquery(root, &paren_select, binder);
482 }
483
484 match resolve::find_table_source(&table_name_node)? {
485 resolve::TableSource::WithTable(with_table) => {
486 hover_qualified_star_columns_from_cte(&with_table)
487 }
488 resolve::TableSource::CreateTable(create_table) => {
489 hover_qualified_star_columns_from_table(&create_table, binder)
490 }
491 resolve::TableSource::CreateView(create_view) => {
492 hover_qualified_star_columns_from_view(&create_view, binder)
493 }
494 resolve::TableSource::CreateMaterializedView(create_materialized_view) => {
495 hover_qualified_star_columns_from_materialized_view(&create_materialized_view, binder)
496 }
497 }
498}
499
500fn hover_qualified_star_columns_from_table(
501 create_table: &impl ast::HasCreateTable,
502 binder: &binder::Binder,
503) -> Option<String> {
504 let path = create_table.path()?;
505 let (schema, table_name) = resolve::resolve_table_info(binder, &path)?;
506 let schema = schema.to_string();
507 let results: Vec<String> = resolve::collect_table_columns(create_table)
508 .into_iter()
509 .filter_map(|column| {
510 let column_name = Name::from_node(&column.name()?);
511 let ty = column.ty()?;
512 let ty = &ty.syntax().text().to_string();
513 Some(ColumnHover::schema_table_column_type(
514 &schema,
515 &table_name,
516 &column_name.to_string(),
517 ty,
518 ))
519 })
520 .collect();
521
522 if results.is_empty() {
523 return None;
524 }
525
526 Some(results.join("\n"))
527}
528
529fn hover_qualified_star_columns_from_cte(with_table: &ast::WithTable) -> Option<String> {
530 let cte_name = Name::from_node(&with_table.name()?);
531 let column_names = resolve::collect_with_table_column_names(with_table);
532 let results: Vec<String> = column_names
533 .iter()
534 .map(|column_name| {
535 ColumnHover::table_column(&cte_name.to_string(), &column_name.to_string())
536 })
537 .collect();
538
539 if results.is_empty() {
540 return None;
541 }
542
543 Some(results.join("\n"))
544}
545
546fn hover_qualified_star_columns_from_view(
547 create_view: &ast::CreateView,
548 binder: &binder::Binder,
549) -> Option<String> {
550 let path = create_view.path()?;
551 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
552
553 let schema_str = schema.to_string();
554 let column_names = resolve::collect_view_column_names(create_view);
555 let results: Vec<String> = column_names
556 .iter()
557 .map(|column_name| {
558 ColumnHover::schema_table_column(&schema_str, &view_name, &column_name.to_string())
559 })
560 .collect();
561
562 if results.is_empty() {
563 return None;
564 }
565
566 Some(results.join("\n"))
567}
568
569fn hover_qualified_star_columns_from_materialized_view(
570 create_materialized_view: &ast::CreateMaterializedView,
571 binder: &binder::Binder,
572) -> Option<String> {
573 let path = create_materialized_view.path()?;
574 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
575
576 let schema_str = schema.to_string();
577 let column_names = resolve::collect_materialized_view_column_names(create_materialized_view);
578 let results: Vec<String> = column_names
579 .iter()
580 .map(|column_name| {
581 ColumnHover::schema_table_column(&schema_str, &view_name, &column_name.to_string())
582 })
583 .collect();
584
585 if results.is_empty() {
586 return None;
587 }
588
589 Some(results.join("\n"))
590}
591
592fn hover_qualified_star_columns_from_subquery(
593 root: &SyntaxNode,
594 paren_select: &ast::ParenSelect,
595 binder: &binder::Binder,
596) -> Option<String> {
597 let ast::SelectVariant::Select(select) = paren_select.select()? else {
598 return None;
599 };
600
601 let select_clause = select.select_clause()?;
602 let target_list = select_clause.target_list()?;
603
604 let mut results = vec![];
605 let subquery_alias = subquery_alias_name(paren_select);
606
607 for target in target_list.targets() {
608 if target.star_token().is_some() {
609 let table_ptrs = resolve::resolve_unqualified_star_tables(binder, &target)?;
610 for table_ptr in table_ptrs {
611 if let Some(columns) = hover_qualified_star_columns(root, &table_ptr, binder) {
612 results.push(columns)
613 }
614 }
615 continue;
616 }
617
618 if let Some(result) =
619 hover_subquery_target_column(root, &target, subquery_alias.as_ref(), binder)
620 {
621 results.push(result);
622 }
623 }
624
625 if results.is_empty() {
626 return None;
627 }
628
629 Some(results.join("\n"))
630}
631
632fn subquery_alias_name(paren_select: &ast::ParenSelect) -> Option<Name> {
633 let from_item = paren_select
634 .syntax()
635 .ancestors()
636 .find_map(ast::FromItem::cast)?;
637 let alias_name = from_item.alias()?.name()?;
638 Some(Name::from_node(&alias_name))
639}
640
641fn hover_subquery_target_column(
642 root: &SyntaxNode,
643 target: &ast::Target,
644 subquery_alias: Option<&Name>,
645 binder: &binder::Binder,
646) -> Option<String> {
647 if let Some(alias) = subquery_alias
648 && let Some((col_name, _node)) = ColumnName::from_target(target.clone())
649 && let Some(col_name) = col_name.to_string()
650 {
651 return Some(ColumnHover::table_column(&alias.to_string(), &col_name));
652 }
653
654 match target.expr()? {
655 ast::Expr::NameRef(name_ref) => hover_column(root, &name_ref, binder),
656 ast::Expr::FieldExpr(field_expr) => {
657 let field = field_expr.field()?;
658 hover_column(root, &field, binder)
659 }
660 _ => None,
661 }
662}
663
664fn hover_index(
665 root: &SyntaxNode,
666 name_ref: &ast::NameRef,
667 binder: &binder::Binder,
668) -> Option<String> {
669 let index_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
670 .into_iter()
671 .next()?;
672
673 let index_name_node = index_ptr.to_node(root);
674
675 let create_index = index_name_node
676 .ancestors()
677 .find_map(ast::CreateIndex::cast)?;
678
679 format_create_index(&create_index, binder)
680}
681
682fn hover_sequence(
683 root: &SyntaxNode,
684 name_ref: &ast::NameRef,
685 binder: &binder::Binder,
686) -> Option<String> {
687 let sequence_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
688 .into_iter()
689 .next()?;
690
691 let sequence_name_node = sequence_ptr.to_node(root);
692
693 let create_sequence = sequence_name_node
694 .ancestors()
695 .find_map(ast::CreateSequence::cast)?;
696
697 format_create_sequence(&create_sequence, binder)
698}
699
700fn hover_tablespace(
701 root: &SyntaxNode,
702 name_ref: &ast::NameRef,
703 binder: &binder::Binder,
704) -> Option<String> {
705 let tablespace_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
706 .into_iter()
707 .next()?;
708 let tablespace_name_node = tablespace_ptr.to_node(root);
709 Some(format!("tablespace {}", tablespace_name_node.text()))
710}
711
712fn hover_database(
713 root: &SyntaxNode,
714 name_ref: &ast::NameRef,
715 binder: &binder::Binder,
716) -> Option<String> {
717 let database_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
718 .into_iter()
719 .next()?;
720 let database_name_node = database_ptr.to_node(root);
721 Some(format!("database {}", database_name_node.text()))
722}
723
724fn hover_server(
725 root: &SyntaxNode,
726 name_ref: &ast::NameRef,
727 binder: &binder::Binder,
728) -> Option<String> {
729 let server_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
730 .into_iter()
731 .next()?;
732 let server_name_node = server_ptr.to_node(root);
733 Some(format!("server {}", server_name_node.text()))
734}
735
736fn hover_type(
737 root: &SyntaxNode,
738 name_ref: &ast::NameRef,
739 binder: &binder::Binder,
740) -> Option<String> {
741 let type_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
742 .into_iter()
743 .next()?;
744
745 let type_name_node = type_ptr.to_node(root);
746
747 let create_type = type_name_node.ancestors().find_map(ast::CreateType::cast)?;
748
749 format_create_type(&create_type, binder)
750}
751
752fn format_create_table(
753 create_table: &impl ast::HasCreateTable,
754 binder: &binder::Binder,
755) -> Option<String> {
756 let path = create_table.path()?;
757 let (schema, table_name) = resolve::resolve_table_info(binder, &path)?;
758 let schema = schema.to_string();
759 let args = create_table.table_arg_list()?.syntax().text().to_string();
760
761 let foreign = if create_table.syntax().kind() == SyntaxKind::CREATE_FOREIGN_TABLE {
762 "foreign "
763 } else {
764 ""
765 };
766
767 Some(format!("{foreign}table {schema}.{table_name}{args}"))
768}
769
770fn format_create_view(create_view: &ast::CreateView, binder: &binder::Binder) -> Option<String> {
771 let path = create_view.path()?;
772 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
773 let schema = schema.to_string();
774
775 let column_list = create_view
776 .column_list()
777 .map(|cl| cl.syntax().text().to_string())
778 .unwrap_or_default();
779
780 let query = create_view.query()?.syntax().text().to_string();
781
782 Some(format!(
783 "view {}.{}{} as {}",
784 schema, view_name, column_list, query
785 ))
786}
787
788fn format_create_materialized_view(
789 create_materialized_view: &ast::CreateMaterializedView,
790 binder: &binder::Binder,
791) -> Option<String> {
792 let path = create_materialized_view.path()?;
793 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
794 let schema = schema.to_string();
795
796 let column_list = create_materialized_view
797 .column_list()
798 .map(|cl| cl.syntax().text().to_string())
799 .unwrap_or_default();
800
801 let query = create_materialized_view
802 .query()?
803 .syntax()
804 .text()
805 .to_string();
806
807 Some(format!(
808 "materialized view {}.{}{} as {}",
809 schema, view_name, column_list, query
810 ))
811}
812
813fn format_view_column(
814 create_view: &ast::CreateView,
815 column_name: Name,
816 binder: &binder::Binder,
817) -> Option<String> {
818 let path = create_view.path()?;
819 let (schema, view_name) = resolve::resolve_view_info(binder, &path)?;
820 Some(ColumnHover::schema_table_column(
821 &schema.to_string(),
822 &view_name,
823 &column_name.to_string(),
824 ))
825}
826
827fn format_with_table(with_table: &ast::WithTable) -> Option<String> {
828 let name = with_table.name()?.syntax().text().to_string();
829 let query = with_table.query()?.syntax().text().to_string();
830 Some(format!("with {} as ({})", name, query))
831}
832
833fn format_create_index(create_index: &ast::CreateIndex, binder: &binder::Binder) -> Option<String> {
834 let index_name = create_index.name()?.syntax().text().to_string();
835
836 let index_schema = index_schema(create_index, binder)?;
837
838 let relation_name = create_index.relation_name()?;
839 let path = relation_name.path()?;
840 let (table_schema, table_name) = resolve::resolve_table_info(binder, &path)?;
841
842 let partition_item_list = create_index.partition_item_list()?;
843 let columns = partition_item_list.syntax().text().to_string();
844
845 Some(format!(
846 "index {}.{} on {}.{}{}",
847 index_schema, index_name, table_schema, table_name, columns
848 ))
849}
850
851fn format_create_sequence(
852 create_sequence: &ast::CreateSequence,
853 binder: &binder::Binder,
854) -> Option<String> {
855 let path = create_sequence.path()?;
856 let (schema, sequence_name) = resolve::resolve_sequence_info(binder, &path)?;
857
858 Some(format!("sequence {}.{}", schema, sequence_name))
859}
860
861fn format_create_tablespace(create_tablespace: &ast::CreateTablespace) -> Option<String> {
862 let name = create_tablespace.name()?.syntax().text().to_string();
863 Some(format!("tablespace {}", name))
864}
865
866fn format_create_database(create_database: &ast::CreateDatabase) -> Option<String> {
867 let name = create_database.name()?.syntax().text().to_string();
868 Some(format!("database {}", name))
869}
870
871fn format_create_server(create_server: &ast::CreateServer) -> Option<String> {
872 let name = create_server.name()?.syntax().text().to_string();
873 Some(format!("server {}", name))
874}
875
876fn index_schema(create_index: &ast::CreateIndex, binder: &binder::Binder) -> Option<String> {
877 let position = create_index.syntax().text_range().start();
878 let search_path = binder.search_path_at(position);
879 search_path.first().map(|s| s.to_string())
880}
881
882fn format_create_type(create_type: &ast::CreateType, binder: &binder::Binder) -> Option<String> {
883 let path = create_type.path()?;
884 let (schema, type_name) = resolve::resolve_type_info(binder, &path)?;
885
886 if let Some(variant_list) = create_type.variant_list() {
887 let variants = variant_list.syntax().text().to_string();
888 return Some(format!(
889 "type {}.{} as enum {}",
890 schema, type_name, variants
891 ));
892 }
893
894 if let Some(column_list) = create_type.column_list() {
895 let columns = column_list.syntax().text().to_string();
896 return Some(format!("type {}.{} as {}", schema, type_name, columns));
897 }
898
899 if let Some(attribute_list) = create_type.attribute_list() {
900 let attributes = attribute_list.syntax().text().to_string();
901 return Some(format!("type {}.{} {}", schema, type_name, attributes));
902 }
903
904 Some(format!("type {}.{}", schema, type_name))
905}
906
907fn hover_schema(
908 root: &SyntaxNode,
909 name_ref: &ast::NameRef,
910 binder: &binder::Binder,
911) -> Option<String> {
912 let schema_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
913 .into_iter()
914 .next()?;
915
916 let schema_name_node = schema_ptr.to_node(root);
917
918 let create_schema = schema_name_node
919 .ancestors()
920 .find_map(ast::CreateSchema::cast)?;
921
922 format_create_schema(&create_schema)
923}
924
925fn create_schema_name(create_schema: &ast::CreateSchema) -> Option<String> {
926 if let Some(schema_name) = create_schema.name() {
927 return Some(schema_name.syntax().text().to_string());
928 }
929
930 create_schema
931 .schema_authorization()
932 .and_then(|authorization| authorization.role())
933 .and_then(|role| role.name_ref())
934 .map(|name_ref| name_ref.syntax().text().to_string())
935}
936
937fn format_create_schema(create_schema: &ast::CreateSchema) -> Option<String> {
938 let schema_name = create_schema_name(create_schema)?;
939 Some(format!("schema {}", schema_name))
940}
941
942fn hover_function(
943 root: &SyntaxNode,
944 name_ref: &ast::NameRef,
945 binder: &binder::Binder,
946) -> Option<String> {
947 let function_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
948 .into_iter()
949 .next()?;
950
951 let function_name_node = function_ptr.to_node(root);
952
953 let create_function = function_name_node
954 .ancestors()
955 .find_map(ast::CreateFunction::cast)?;
956
957 format_create_function(&create_function, binder)
958}
959
960fn format_create_function(
961 create_function: &ast::CreateFunction,
962 binder: &binder::Binder,
963) -> Option<String> {
964 let path = create_function.path()?;
965 let (schema, function_name) = resolve::resolve_function_info(binder, &path)?;
966
967 let param_list = create_function.param_list()?;
968 let params = param_list.syntax().text().to_string();
969
970 let ret_type = create_function.ret_type()?;
971 let return_type = ret_type.syntax().text().to_string();
972
973 Some(format!(
974 "function {}.{}{} {}",
975 schema, function_name, params, return_type
976 ))
977}
978
979fn hover_aggregate(
980 root: &SyntaxNode,
981 name_ref: &ast::NameRef,
982 binder: &binder::Binder,
983) -> Option<String> {
984 let aggregate_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
985 .into_iter()
986 .next()?;
987
988 let aggregate_name_node = aggregate_ptr.to_node(root);
989
990 let create_aggregate = aggregate_name_node
991 .ancestors()
992 .find_map(ast::CreateAggregate::cast)?;
993
994 format_create_aggregate(&create_aggregate, binder)
995}
996
997fn format_create_aggregate(
998 create_aggregate: &ast::CreateAggregate,
999 binder: &binder::Binder,
1000) -> Option<String> {
1001 let path = create_aggregate.path()?;
1002 let (schema, aggregate_name) = resolve::resolve_aggregate_info(binder, &path)?;
1003
1004 let param_list = create_aggregate.param_list()?;
1005 let params = param_list.syntax().text().to_string();
1006
1007 Some(format!("aggregate {}.{}{}", schema, aggregate_name, params))
1008}
1009
1010fn hover_procedure(
1011 root: &SyntaxNode,
1012 name_ref: &ast::NameRef,
1013 binder: &binder::Binder,
1014) -> Option<String> {
1015 let procedure_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
1016 .into_iter()
1017 .next()?;
1018
1019 let procedure_name_node = procedure_ptr.to_node(root);
1020
1021 let create_procedure = procedure_name_node
1022 .ancestors()
1023 .find_map(ast::CreateProcedure::cast)?;
1024
1025 format_create_procedure(&create_procedure, binder)
1026}
1027
1028fn format_create_procedure(
1029 create_procedure: &ast::CreateProcedure,
1030 binder: &binder::Binder,
1031) -> Option<String> {
1032 let path = create_procedure.path()?;
1033 let (schema, procedure_name) = resolve::resolve_procedure_info(binder, &path)?;
1034
1035 let param_list = create_procedure.param_list()?;
1036 let params = param_list.syntax().text().to_string();
1037
1038 Some(format!("procedure {}.{}{}", schema, procedure_name, params))
1039}
1040
1041fn hover_routine(
1042 root: &SyntaxNode,
1043 name_ref: &ast::NameRef,
1044 binder: &binder::Binder,
1045) -> Option<String> {
1046 let routine_ptr = resolve::resolve_name_ref(binder, root, name_ref)?
1047 .into_iter()
1048 .next()?;
1049 let routine_name = routine_ptr.to_node(root);
1050
1051 for a in routine_name.ancestors() {
1052 if let Some(create_function) = ast::CreateFunction::cast(a.clone()) {
1053 return format_create_function(&create_function, binder);
1054 }
1055 if let Some(create_aggregate) = ast::CreateAggregate::cast(a.clone()) {
1056 return format_create_aggregate(&create_aggregate, binder);
1057 }
1058 if let Some(create_procedure) = ast::CreateProcedure::cast(a) {
1059 return format_create_procedure(&create_procedure, binder);
1060 }
1061 }
1062
1063 None
1064}
1065
1066#[cfg(test)]
1067mod test {
1068 use crate::hover::hover;
1069 use crate::test_utils::fixture;
1070 use annotate_snippets::{AnnotationKind, Level, Renderer, Snippet, renderer::DecorStyle};
1071 use insta::assert_snapshot;
1072 use squawk_syntax::ast;
1073
1074 #[track_caller]
1075 fn check_hover(sql: &str) -> String {
1076 check_hover_(sql).expect("should find hover information")
1077 }
1078
1079 #[track_caller]
1080 fn check_hover_(sql: &str) -> Option<String> {
1081 let (mut offset, sql) = fixture(sql);
1082 offset = offset.checked_sub(1.into()).unwrap_or_default();
1083 let parse = ast::SourceFile::parse(&sql);
1084 assert_eq!(parse.errors(), vec![]);
1085 let file: ast::SourceFile = parse.tree();
1086
1087 if let Some(type_info) = hover(&file, offset) {
1088 let offset_usize: usize = offset.into();
1089 let title = format!("hover: {}", type_info);
1090 let group = Level::INFO.primary_title(&title).element(
1091 Snippet::source(&sql).fold(true).annotation(
1092 AnnotationKind::Context
1093 .span(offset_usize..offset_usize + 1)
1094 .label("hover"),
1095 ),
1096 );
1097 let renderer = Renderer::plain().decor_style(DecorStyle::Unicode);
1098 return Some(
1099 renderer
1100 .render(&[group])
1101 .to_string()
1102 .replace("info: hover:", "hover:"),
1104 );
1105 }
1106 None
1107 }
1108
1109 #[test]
1110 fn hover_column_in_create_index() {
1111 assert_snapshot!(check_hover("
1112create table users(id int, email text);
1113create index idx_email on users(email$0);
1114"), @r"
1115 hover: column public.users.email text
1116 ╭▸
1117 3 │ create index idx_email on users(email);
1118 ╰╴ ─ hover
1119 ");
1120 }
1121
1122 #[test]
1123 fn hover_column_int_type() {
1124 assert_snapshot!(check_hover("
1125create table users(id int, email text);
1126create index idx_id on users(id$0);
1127"), @r"
1128 hover: column public.users.id int
1129 ╭▸
1130 3 │ create index idx_id on users(id);
1131 ╰╴ ─ hover
1132 ");
1133 }
1134
1135 #[test]
1136 fn hover_column_with_schema() {
1137 assert_snapshot!(check_hover("
1138create table public.users(id int, email text);
1139create index idx_email on public.users(email$0);
1140"), @r"
1141 hover: column public.users.email text
1142 ╭▸
1143 3 │ create index idx_email on public.users(email);
1144 ╰╴ ─ hover
1145 ");
1146 }
1147
1148 #[test]
1149 fn hover_column_temp_table() {
1150 assert_snapshot!(check_hover("
1151create temp table users(id int, email text);
1152create index idx_email on users(email$0);
1153"), @r"
1154 hover: column pg_temp.users.email text
1155 ╭▸
1156 3 │ create index idx_email on users(email);
1157 ╰╴ ─ hover
1158 ");
1159 }
1160
1161 #[test]
1162 fn hover_column_multiple_columns() {
1163 assert_snapshot!(check_hover("
1164create table users(id int, email text, name varchar(100));
1165create index idx_users on users(id, email$0, name);
1166"), @r"
1167 hover: column public.users.email text
1168 ╭▸
1169 3 │ create index idx_users on users(id, email, name);
1170 ╰╴ ─ hover
1171 ");
1172 }
1173
1174 #[test]
1175 fn hover_column_varchar() {
1176 assert_snapshot!(check_hover("
1177create table users(id int, name varchar(100));
1178create index idx_name on users(name$0);
1179"), @r"
1180 hover: column public.users.name varchar(100)
1181 ╭▸
1182 3 │ create index idx_name on users(name);
1183 ╰╴ ─ hover
1184 ");
1185 }
1186
1187 #[test]
1188 fn hover_column_bigint() {
1189 assert_snapshot!(check_hover("
1190create table metrics(value bigint);
1191create index idx_value on metrics(value$0);
1192"), @r"
1193 hover: column public.metrics.value bigint
1194 ╭▸
1195 3 │ create index idx_value on metrics(value);
1196 ╰╴ ─ hover
1197 ");
1198 }
1199
1200 #[test]
1201 fn hover_column_timestamp() {
1202 assert_snapshot!(check_hover("
1203create table events(created_at timestamp with time zone);
1204create index idx_created on events(created_at$0);
1205"), @r"
1206 hover: column public.events.created_at timestamp with time zone
1207 ╭▸
1208 3 │ create index idx_created on events(created_at);
1209 ╰╴ ─ hover
1210 ");
1211 }
1212
1213 #[test]
1214 fn hover_column_with_search_path() {
1215 assert_snapshot!(check_hover(r#"
1216set search_path to myschema;
1217create table myschema.users(id int, email text);
1218create index idx_email on users(email$0);
1219"#), @r"
1220 hover: column myschema.users.email text
1221 ╭▸
1222 4 │ create index idx_email on users(email);
1223 ╰╴ ─ hover
1224 ");
1225 }
1226
1227 #[test]
1228 fn hover_column_explicit_schema_overrides_search_path() {
1229 assert_snapshot!(check_hover(r#"
1230set search_path to myschema;
1231create table public.users(id int, email text);
1232create table myschema.users(value bigint);
1233create index idx_email on public.users(email$0);
1234"#), @r"
1235 hover: column public.users.email text
1236 ╭▸
1237 5 │ create index idx_email on public.users(email);
1238 ╰╴ ─ hover
1239 ");
1240 }
1241
1242 #[test]
1243 fn hover_on_table_name() {
1244 assert_snapshot!(check_hover("
1245create table t(id int);
1246create index idx on t$0(id);
1247"), @r"
1248 hover: table public.t(id int)
1249 ╭▸
1250 3 │ create index idx on t(id);
1251 ╰╴ ─ hover
1252 ");
1253 }
1254
1255 #[test]
1256 fn hover_on_index_name_in_create() {
1257 assert_snapshot!(check_hover("
1258create table users(id int);
1259create index idx$0 on users(id);
1260"), @r"
1261 hover: index public.idx on public.users(id)
1262 ╭▸
1263 3 │ create index idx on users(id);
1264 ╰╴ ─ hover
1265 ");
1266 }
1267
1268 #[test]
1269 fn hover_table_in_create_index() {
1270 assert_snapshot!(check_hover("
1271create table users(id int, email text);
1272create index idx_email on users$0(email);
1273"), @r"
1274 hover: table public.users(id int, email text)
1275 ╭▸
1276 3 │ create index idx_email on users(email);
1277 ╰╴ ─ hover
1278 ");
1279 }
1280
1281 #[test]
1282 fn hover_table_with_schema() {
1283 assert_snapshot!(check_hover("
1284create table public.users(id int, email text);
1285create index idx on public.users$0(id);
1286"), @r"
1287 hover: table public.users(id int, email text)
1288 ╭▸
1289 3 │ create index idx on public.users(id);
1290 ╰╴ ─ hover
1291 ");
1292 }
1293
1294 #[test]
1295 fn hover_table_temp() {
1296 assert_snapshot!(check_hover("
1297create temp table users(id int, email text);
1298create index idx on users$0(id);
1299"), @r"
1300 hover: table pg_temp.users(id int, email text)
1301 ╭▸
1302 3 │ create index idx on users(id);
1303 ╰╴ ─ hover
1304 ");
1305 }
1306
1307 #[test]
1308 fn hover_table_multiline() {
1309 assert_snapshot!(check_hover("
1310create table users(
1311 id int,
1312 email text,
1313 name varchar(100)
1314);
1315create index idx on users$0(id);
1316"), @r"
1317 hover: table public.users(
1318 id int,
1319 email text,
1320 name varchar(100)
1321 )
1322 ╭▸
1323 7 │ create index idx on users(id);
1324 ╰╴ ─ hover
1325 ");
1326 }
1327
1328 #[test]
1329 fn hover_table_with_search_path() {
1330 assert_snapshot!(check_hover(r#"
1331set search_path to myschema;
1332create table users(id int, email text);
1333create index idx on users$0(id);
1334"#), @r"
1335 hover: table myschema.users(id int, email text)
1336 ╭▸
1337 4 │ create index idx on users(id);
1338 ╰╴ ─ hover
1339 ");
1340 }
1341
1342 #[test]
1343 fn hover_table_search_path_at_definition() {
1344 assert_snapshot!(check_hover(r#"
1345set search_path to myschema;
1346create table users(id int, email text);
1347set search_path to myschema, otherschema;
1348create index idx on users$0(id);
1349"#), @r"
1350 hover: table myschema.users(id int, email text)
1351 ╭▸
1352 5 │ create index idx on users(id);
1353 ╰╴ ─ hover
1354 ");
1355 }
1356
1357 #[test]
1358 fn hover_on_create_table_definition() {
1359 assert_snapshot!(check_hover("
1360create table t$0(x bigint);
1361"), @r"
1362 hover: table public.t(x bigint)
1363 ╭▸
1364 2 │ create table t(x bigint);
1365 ╰╴ ─ hover
1366 ");
1367 }
1368
1369 #[test]
1370 fn hover_on_create_table_definition_with_schema() {
1371 assert_snapshot!(check_hover("
1372create table myschema.users$0(id int);
1373"), @r"
1374 hover: table myschema.users(id int)
1375 ╭▸
1376 2 │ create table myschema.users(id int);
1377 ╰╴ ─ hover
1378 ");
1379 }
1380
1381 #[test]
1382 fn hover_on_create_temp_table_definition() {
1383 assert_snapshot!(check_hover("
1384create temp table t$0(x bigint);
1385"), @r"
1386 hover: table pg_temp.t(x bigint)
1387 ╭▸
1388 2 │ create temp table t(x bigint);
1389 ╰╴ ─ hover
1390 ");
1391 }
1392
1393 #[test]
1394 fn hover_on_column_in_create_table() {
1395 assert_snapshot!(check_hover("
1396create table t(id$0 int);
1397"), @r"
1398 hover: column public.t.id int
1399 ╭▸
1400 2 │ create table t(id int);
1401 ╰╴ ─ hover
1402 ");
1403 }
1404
1405 #[test]
1406 fn hover_on_column_in_create_table_with_schema() {
1407 assert_snapshot!(check_hover("
1408create table myschema.users(id$0 int, name text);
1409"), @r"
1410 hover: column myschema.users.id int
1411 ╭▸
1412 2 │ create table myschema.users(id int, name text);
1413 ╰╴ ─ hover
1414 ");
1415 }
1416
1417 #[test]
1418 fn hover_on_column_in_temp_table() {
1419 assert_snapshot!(check_hover("
1420create temp table t(x$0 bigint);
1421"), @r"
1422 hover: column pg_temp.t.x bigint
1423 ╭▸
1424 2 │ create temp table t(x bigint);
1425 ╰╴ ─ hover
1426 ");
1427 }
1428
1429 #[test]
1430 fn hover_on_multiple_columns() {
1431 assert_snapshot!(check_hover("
1432create table t(id int, email$0 text, name varchar(100));
1433"), @r"
1434 hover: column public.t.email text
1435 ╭▸
1436 2 │ create table t(id int, email text, name varchar(100));
1437 ╰╴ ─ hover
1438 ");
1439 }
1440
1441 #[test]
1442 fn hover_on_drop_table() {
1443 assert_snapshot!(check_hover("
1444create table users(id int, email text);
1445drop table users$0;
1446"), @r"
1447 hover: table public.users(id int, email text)
1448 ╭▸
1449 3 │ drop table users;
1450 ╰╴ ─ hover
1451 ");
1452 }
1453
1454 #[test]
1455 fn hover_on_drop_table_with_schema() {
1456 assert_snapshot!(check_hover("
1457create table myschema.users(id int);
1458drop table myschema.users$0;
1459"), @r"
1460 hover: table myschema.users(id int)
1461 ╭▸
1462 3 │ drop table myschema.users;
1463 ╰╴ ─ hover
1464 ");
1465 }
1466
1467 #[test]
1468 fn hover_on_drop_temp_table() {
1469 assert_snapshot!(check_hover("
1470create temp table t(x bigint);
1471drop table t$0;
1472"), @r"
1473 hover: table pg_temp.t(x bigint)
1474 ╭▸
1475 3 │ drop table t;
1476 ╰╴ ─ hover
1477 ");
1478 }
1479
1480 #[test]
1481 fn hover_on_create_index_definition() {
1482 assert_snapshot!(check_hover("
1483create table t(x bigint);
1484create index idx$0 on t(x);
1485"), @r"
1486 hover: index public.idx on public.t(x)
1487 ╭▸
1488 3 │ create index idx on t(x);
1489 ╰╴ ─ hover
1490 ");
1491 }
1492
1493 #[test]
1494 fn hover_on_drop_index() {
1495 assert_snapshot!(check_hover("
1496create table t(x bigint);
1497create index idx_x on t(x);
1498drop index idx_x$0;
1499"), @r"
1500 hover: index public.idx_x on public.t(x)
1501 ╭▸
1502 4 │ drop index idx_x;
1503 ╰╴ ─ hover
1504 ");
1505 }
1506
1507 #[test]
1508 fn hover_on_create_type_definition() {
1509 assert_snapshot!(check_hover("
1510create type status$0 as enum ('active', 'inactive');
1511"), @r"
1512 hover: type public.status as enum ('active', 'inactive')
1513 ╭▸
1514 2 │ create type status as enum ('active', 'inactive');
1515 ╰╴ ─ hover
1516 ");
1517 }
1518
1519 #[test]
1520 fn hover_on_create_type_definition_with_schema() {
1521 assert_snapshot!(check_hover("
1522create type myschema.status$0 as enum ('active', 'inactive');
1523"), @r"
1524 hover: type myschema.status as enum ('active', 'inactive')
1525 ╭▸
1526 2 │ create type myschema.status as enum ('active', 'inactive');
1527 ╰╴ ─ hover
1528 ");
1529 }
1530
1531 #[test]
1532 fn hover_on_drop_type() {
1533 assert_snapshot!(check_hover("
1534create type status as enum ('active', 'inactive');
1535drop type status$0;
1536"), @r"
1537 hover: type public.status as enum ('active', 'inactive')
1538 ╭▸
1539 3 │ drop type status;
1540 ╰╴ ─ hover
1541 ");
1542 }
1543
1544 #[test]
1545 fn hover_on_drop_type_with_schema() {
1546 assert_snapshot!(check_hover("
1547create type myschema.status as enum ('active', 'inactive');
1548drop type myschema.status$0;
1549"), @r"
1550 hover: type myschema.status as enum ('active', 'inactive')
1551 ╭▸
1552 3 │ drop type myschema.status;
1553 ╰╴ ─ hover
1554 ");
1555 }
1556
1557 #[test]
1558 fn hover_on_create_type_composite() {
1559 assert_snapshot!(check_hover("
1560create type person$0 as (name text, age int);
1561"), @r"
1562 hover: type public.person as (name text, age int)
1563 ╭▸
1564 2 │ create type person as (name text, age int);
1565 ╰╴ ─ hover
1566 ");
1567 }
1568
1569 #[test]
1570 fn hover_on_drop_type_composite() {
1571 assert_snapshot!(check_hover("
1572create type person as (name text, age int);
1573drop type person$0;
1574"), @r"
1575 hover: type public.person as (name text, age int)
1576 ╭▸
1577 3 │ drop type person;
1578 ╰╴ ─ hover
1579 ");
1580 }
1581
1582 #[test]
1583 fn hover_on_create_type_range() {
1584 assert_snapshot!(check_hover("
1585create type int4_range$0 as range (subtype = int4);
1586"), @r"
1587 hover: type public.int4_range (subtype = int4)
1588 ╭▸
1589 2 │ create type int4_range as range (subtype = int4);
1590 ╰╴ ─ hover
1591 ");
1592 }
1593
1594 #[test]
1595 fn hover_on_drop_type_range() {
1596 assert_snapshot!(check_hover("
1597create type int4_range as range (subtype = int4);
1598drop type int4_range$0;
1599"), @r"
1600 hover: type public.int4_range (subtype = int4)
1601 ╭▸
1602 3 │ drop type int4_range;
1603 ╰╴ ─ hover
1604 ");
1605 }
1606
1607 #[test]
1608 fn hover_on_cast_operator() {
1609 assert_snapshot!(check_hover("
1610create type foo as enum ('a', 'b');
1611select x::foo$0;
1612"), @r"
1613 hover: type public.foo as enum ('a', 'b')
1614 ╭▸
1615 3 │ select x::foo;
1616 ╰╴ ─ hover
1617 ");
1618 }
1619
1620 #[test]
1621 fn hover_on_cast_function() {
1622 assert_snapshot!(check_hover("
1623create type bar as enum ('x', 'y');
1624select cast(x as bar$0);
1625"), @r"
1626 hover: type public.bar as enum ('x', 'y')
1627 ╭▸
1628 3 │ select cast(x as bar);
1629 ╰╴ ─ hover
1630 ");
1631 }
1632
1633 #[test]
1634 fn hover_on_cast_with_schema() {
1635 assert_snapshot!(check_hover("
1636create type myschema.baz as enum ('m', 'n');
1637select x::myschema.baz$0;
1638"), @r"
1639 hover: type myschema.baz as enum ('m', 'n')
1640 ╭▸
1641 3 │ select x::myschema.baz;
1642 ╰╴ ─ hover
1643 ");
1644 }
1645
1646 #[test]
1647 fn hover_on_drop_function() {
1648 assert_snapshot!(check_hover("
1649create function foo() returns int as $$ select 1 $$ language sql;
1650drop function foo$0();
1651"), @r"
1652 hover: function public.foo() returns int
1653 ╭▸
1654 3 │ drop function foo();
1655 ╰╴ ─ hover
1656 ");
1657 }
1658
1659 #[test]
1660 fn hover_on_drop_function_with_schema() {
1661 assert_snapshot!(check_hover("
1662create function myschema.foo() returns int as $$ select 1 $$ language sql;
1663drop function myschema.foo$0();
1664"), @r"
1665 hover: function myschema.foo() returns int
1666 ╭▸
1667 3 │ drop function myschema.foo();
1668 ╰╴ ─ hover
1669 ");
1670 }
1671
1672 #[test]
1673 fn hover_on_create_function_definition() {
1674 assert_snapshot!(check_hover("
1675create function foo$0() returns int as $$ select 1 $$ language sql;
1676"), @r"
1677 hover: function public.foo() returns int
1678 ╭▸
1679 2 │ create function foo() returns int as $$ select 1 $$ language sql;
1680 ╰╴ ─ hover
1681 ");
1682 }
1683
1684 #[test]
1685 fn hover_on_create_function_with_explicit_schema() {
1686 assert_snapshot!(check_hover("
1687create function myschema.foo$0() returns int as $$ select 1 $$ language sql;
1688"), @r"
1689 hover: function myschema.foo() returns int
1690 ╭▸
1691 2 │ create function myschema.foo() returns int as $$ select 1 $$ language sql;
1692 ╰╴ ─ hover
1693 ");
1694 }
1695
1696 #[test]
1697 fn hover_on_drop_function_with_search_path() {
1698 assert_snapshot!(check_hover(r#"
1699set search_path to myschema;
1700create function foo() returns int as $$ select 1 $$ language sql;
1701drop function foo$0();
1702"#), @r"
1703 hover: function myschema.foo() returns int
1704 ╭▸
1705 4 │ drop function foo();
1706 ╰╴ ─ hover
1707 ");
1708 }
1709
1710 #[test]
1711 fn hover_on_drop_function_overloaded() {
1712 assert_snapshot!(check_hover("
1713create function add(complex) returns complex as $$ select null $$ language sql;
1714create function add(bigint) returns bigint as $$ select 1 $$ language sql;
1715drop function add$0(complex);
1716"), @r"
1717 hover: function public.add(complex) returns complex
1718 ╭▸
1719 4 │ drop function add(complex);
1720 ╰╴ ─ hover
1721 ");
1722 }
1723
1724 #[test]
1725 fn hover_on_drop_function_second_overload() {
1726 assert_snapshot!(check_hover("
1727create function add(complex) returns complex as $$ select null $$ language sql;
1728create function add(bigint) returns bigint as $$ select 1 $$ language sql;
1729drop function add$0(bigint);
1730"), @r"
1731 hover: function public.add(bigint) returns bigint
1732 ╭▸
1733 4 │ drop function add(bigint);
1734 ╰╴ ─ hover
1735 ");
1736 }
1737
1738 #[test]
1739 fn hover_on_drop_aggregate() {
1740 assert_snapshot!(check_hover("
1741create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
1742drop aggregate myavg$0(int);
1743"), @r"
1744 hover: aggregate public.myavg(int)
1745 ╭▸
1746 3 │ drop aggregate myavg(int);
1747 ╰╴ ─ hover
1748 ");
1749 }
1750
1751 #[test]
1752 fn hover_on_drop_aggregate_with_schema() {
1753 assert_snapshot!(check_hover("
1754create aggregate myschema.myavg(int) (sfunc = int4_avg_accum, stype = _int8);
1755drop aggregate myschema.myavg$0(int);
1756"), @r"
1757 hover: aggregate myschema.myavg(int)
1758 ╭▸
1759 3 │ drop aggregate myschema.myavg(int);
1760 ╰╴ ─ hover
1761 ");
1762 }
1763
1764 #[test]
1765 fn hover_on_create_aggregate_definition() {
1766 assert_snapshot!(check_hover("
1767create aggregate myavg$0(int) (sfunc = int4_avg_accum, stype = _int8);
1768"), @r"
1769 hover: aggregate public.myavg(int)
1770 ╭▸
1771 2 │ create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
1772 ╰╴ ─ hover
1773 ");
1774 }
1775
1776 #[test]
1777 fn hover_on_drop_aggregate_with_search_path() {
1778 assert_snapshot!(check_hover(r#"
1779set search_path to myschema;
1780create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
1781drop aggregate myavg$0(int);
1782"#), @r"
1783 hover: aggregate myschema.myavg(int)
1784 ╭▸
1785 4 │ drop aggregate myavg(int);
1786 ╰╴ ─ hover
1787 ");
1788 }
1789
1790 #[test]
1791 fn hover_on_drop_aggregate_overloaded() {
1792 assert_snapshot!(check_hover("
1793create aggregate sum(complex) (sfunc = complex_add, stype = complex, initcond = '(0,0)');
1794create aggregate sum(bigint) (sfunc = bigint_add, stype = bigint, initcond = '0');
1795drop aggregate sum$0(complex);
1796"), @r"
1797 hover: aggregate public.sum(complex)
1798 ╭▸
1799 4 │ drop aggregate sum(complex);
1800 ╰╴ ─ hover
1801 ");
1802 }
1803
1804 #[test]
1805 fn hover_on_drop_aggregate_second_overload() {
1806 assert_snapshot!(check_hover("
1807create aggregate sum(complex) (sfunc = complex_add, stype = complex, initcond = '(0,0)');
1808create aggregate sum(bigint) (sfunc = bigint_add, stype = bigint, initcond = '0');
1809drop aggregate sum$0(bigint);
1810"), @r"
1811 hover: aggregate public.sum(bigint)
1812 ╭▸
1813 4 │ drop aggregate sum(bigint);
1814 ╰╴ ─ hover
1815 ");
1816 }
1817
1818 #[test]
1819 fn hover_on_select_function_call() {
1820 assert_snapshot!(check_hover("
1821create function foo() returns int as $$ select 1 $$ language sql;
1822select foo$0();
1823"), @r"
1824 hover: function public.foo() returns int
1825 ╭▸
1826 3 │ select foo();
1827 ╰╴ ─ hover
1828 ");
1829 }
1830
1831 #[test]
1832 fn hover_on_select_function_call_with_schema() {
1833 assert_snapshot!(check_hover("
1834create function public.foo() returns int as $$ select 1 $$ language sql;
1835select public.foo$0();
1836"), @r"
1837 hover: function public.foo() returns int
1838 ╭▸
1839 3 │ select public.foo();
1840 ╰╴ ─ hover
1841 ");
1842 }
1843
1844 #[test]
1845 fn hover_on_select_function_call_with_search_path() {
1846 assert_snapshot!(check_hover(r#"
1847set search_path to myschema;
1848create function foo() returns int as $$ select 1 $$ language sql;
1849select foo$0();
1850"#), @r"
1851 hover: function myschema.foo() returns int
1852 ╭▸
1853 4 │ select foo();
1854 ╰╴ ─ hover
1855 ");
1856 }
1857
1858 #[test]
1859 fn hover_on_select_function_call_with_params() {
1860 assert_snapshot!(check_hover("
1861create function add(a int, b int) returns int as $$ select a + b $$ language sql;
1862select add$0(1, 2);
1863"), @r"
1864 hover: function public.add(a int, b int) returns int
1865 ╭▸
1866 3 │ select add(1, 2);
1867 ╰╴ ─ hover
1868 ");
1869 }
1870
1871 #[test]
1872 fn hover_on_function_call_style_column_access() {
1873 assert_snapshot!(check_hover("
1874create table t(a int, b int);
1875select a$0(t) from t;
1876"), @r"
1877 hover: column public.t.a int
1878 ╭▸
1879 3 │ select a(t) from t;
1880 ╰╴ ─ hover
1881 ");
1882 }
1883
1884 #[test]
1885 fn hover_on_function_call_style_column_access_with_function_precedence() {
1886 assert_snapshot!(check_hover("
1887create table t(a int, b int);
1888create function b(t) returns int as 'select 1' LANGUAGE sql;
1889select b$0(t) from t;
1890"), @r"
1891 hover: function public.b(t) returns int
1892 ╭▸
1893 4 │ select b(t) from t;
1894 ╰╴ ─ hover
1895 ");
1896 }
1897
1898 #[test]
1899 fn hover_on_function_call_style_table_arg() {
1900 assert_snapshot!(check_hover("
1901create table t(a int, b int);
1902select a(t$0) from t;
1903"), @r"
1904 hover: table public.t(a int, b int)
1905 ╭▸
1906 3 │ select a(t) from t;
1907 ╰╴ ─ hover
1908 ");
1909 }
1910
1911 #[test]
1912 fn hover_on_function_call_style_table_arg_with_function() {
1913 assert_snapshot!(check_hover("
1914create table t(a int, b int);
1915create function b(t) returns int as 'select 1' LANGUAGE sql;
1916select b(t$0) from t;
1917"), @r"
1918 hover: table public.t(a int, b int)
1919 ╭▸
1920 4 │ select b(t) from t;
1921 ╰╴ ─ hover
1922 ");
1923 }
1924
1925 #[test]
1926 fn hover_on_function_call_style_table_arg_in_where() {
1927 assert_snapshot!(check_hover("
1928create table t(a int);
1929select * from t where a(t$0) > 2;
1930"), @r"
1931 hover: table public.t(a int)
1932 ╭▸
1933 3 │ select * from t where a(t) > 2;
1934 ╰╴ ─ hover
1935 ");
1936 }
1937
1938 #[test]
1939 fn hover_on_qualified_table_ref_in_where() {
1940 assert_snapshot!(check_hover("
1941create table t(a int);
1942create function b(t) returns int as 'select 1' language sql;
1943select * from t where t$0.b > 2;
1944"), @r"
1945 hover: table public.t(a int)
1946 ╭▸
1947 4 │ select * from t where t.b > 2;
1948 ╰╴ ─ hover
1949 ");
1950 }
1951
1952 #[test]
1953 fn hover_on_field_style_function_call() {
1954 assert_snapshot!(check_hover("
1955create table t(a int);
1956create function b(t) returns int as 'select 1' language sql;
1957select t.b$0 from t;
1958"), @r"
1959 hover: function public.b(t) returns int
1960 ╭▸
1961 4 │ select t.b from t;
1962 ╰╴ ─ hover
1963 ");
1964 }
1965
1966 #[test]
1967 fn hover_on_field_style_function_call_column_precedence() {
1968 assert_snapshot!(check_hover("
1969create table t(a int, b int);
1970create function b(t) returns int as 'select 1' language sql;
1971select t.b$0 from t;
1972"), @r"
1973 hover: column public.t.b int
1974 ╭▸
1975 4 │ select t.b from t;
1976 ╰╴ ─ hover
1977 ");
1978 }
1979
1980 #[test]
1981 fn hover_on_field_style_function_call_table_ref() {
1982 assert_snapshot!(check_hover("
1983create table t(a int);
1984create function b(t) returns int as 'select 1' language sql;
1985select t$0.b from t;
1986"), @r"
1987 hover: table public.t(a int)
1988 ╭▸
1989 4 │ select t.b from t;
1990 ╰╴ ─ hover
1991 ");
1992 }
1993
1994 #[test]
1995 fn hover_on_select_from_table() {
1996 assert_snapshot!(check_hover("
1997create table users(id int, email text);
1998select * from users$0;
1999"), @r"
2000 hover: table public.users(id int, email text)
2001 ╭▸
2002 3 │ select * from users;
2003 ╰╴ ─ hover
2004 ");
2005 }
2006
2007 #[test]
2008 fn hover_on_subquery_qualified_table_ref() {
2009 assert_snapshot!(check_hover("
2010select t$0.a from (select 1 a) t;
2011"), @r"
2012 hover: subquery t as (select 1 a)
2013 ╭▸
2014 2 │ select t.a from (select 1 a) t;
2015 ╰╴ ─ hover
2016 ");
2017 }
2018
2019 #[test]
2020 fn hover_on_subquery_qualified_column_ref() {
2021 assert_snapshot!(check_hover("
2022select t.a$0 from (select 1 a) t;
2023"), @r"
2024 hover: column t.a
2025 ╭▸
2026 2 │ select t.a from (select 1 a) t;
2027 ╰╴ ─ hover
2028 ");
2029 }
2030
2031 #[test]
2032 fn hover_on_select_from_table_with_schema() {
2033 assert_snapshot!(check_hover("
2034create table public.users(id int, email text);
2035select * from public.users$0;
2036"), @r"
2037 hover: table public.users(id int, email text)
2038 ╭▸
2039 3 │ select * from public.users;
2040 ╰╴ ─ hover
2041 ");
2042 }
2043
2044 #[test]
2045 fn hover_on_select_from_table_with_search_path() {
2046 assert_snapshot!(check_hover("
2047set search_path to foo;
2048create table foo.users(id int, email text);
2049select * from users$0;
2050"), @r"
2051 hover: table foo.users(id int, email text)
2052 ╭▸
2053 4 │ select * from users;
2054 ╰╴ ─ hover
2055 ");
2056 }
2057
2058 #[test]
2059 fn hover_on_select_from_temp_table() {
2060 assert_snapshot!(check_hover("
2061create temp table users(id int, email text);
2062select * from users$0;
2063"), @r"
2064 hover: table pg_temp.users(id int, email text)
2065 ╭▸
2066 3 │ select * from users;
2067 ╰╴ ─ hover
2068 ");
2069 }
2070
2071 #[test]
2072 fn hover_on_select_from_multiline_table() {
2073 assert_snapshot!(check_hover("
2074create table users(
2075 id int,
2076 email text,
2077 name varchar(100)
2078);
2079select * from users$0;
2080"), @r"
2081 hover: table public.users(
2082 id int,
2083 email text,
2084 name varchar(100)
2085 )
2086 ╭▸
2087 7 │ select * from users;
2088 ╰╴ ─ hover
2089 ");
2090 }
2091
2092 #[test]
2093 fn hover_on_select_column() {
2094 assert_snapshot!(check_hover("
2095create table users(id int, email text);
2096select id$0 from users;
2097"), @r"
2098 hover: column public.users.id int
2099 ╭▸
2100 3 │ select id from users;
2101 ╰╴ ─ hover
2102 ");
2103 }
2104
2105 #[test]
2106 fn hover_on_select_column_second() {
2107 assert_snapshot!(check_hover("
2108create table users(id int, email text);
2109select id, email$0 from users;
2110"), @r"
2111 hover: column public.users.email text
2112 ╭▸
2113 3 │ select id, email from users;
2114 ╰╴ ─ hover
2115 ");
2116 }
2117
2118 #[test]
2119 fn hover_on_select_column_with_schema() {
2120 assert_snapshot!(check_hover("
2121create table public.users(id int, email text);
2122select email$0 from public.users;
2123"), @r"
2124 hover: column public.users.email text
2125 ╭▸
2126 3 │ select email from public.users;
2127 ╰╴ ─ hover
2128 ");
2129 }
2130
2131 #[test]
2132 fn hover_on_select_column_with_search_path() {
2133 assert_snapshot!(check_hover("
2134set search_path to foo;
2135create table foo.users(id int, email text);
2136select id$0 from users;
2137"), @r"
2138 hover: column foo.users.id int
2139 ╭▸
2140 4 │ select id from users;
2141 ╰╴ ─ hover
2142 ");
2143 }
2144
2145 #[test]
2146 fn hover_on_select_qualified_star() {
2147 assert_snapshot!(check_hover("
2148create table u(id int, b int);
2149select u.*$0 from u;
2150"), @r"
2151 hover: column public.u.id int
2152 column public.u.b int
2153 ╭▸
2154 3 │ select u.* from u;
2155 ╰╴ ─ hover
2156 ");
2157 }
2158
2159 #[test]
2160 fn hover_on_select_unqualified_star() {
2161 assert_snapshot!(check_hover("
2162create table u(id int, b int);
2163select *$0 from u;
2164"), @r"
2165 hover: column public.u.id int
2166 column public.u.b int
2167 ╭▸
2168 3 │ select * from u;
2169 ╰╴ ─ hover
2170 ");
2171 }
2172
2173 #[test]
2174 fn hover_on_select_count_star() {
2175 assert_snapshot!(check_hover("
2176create table u(id int, b int);
2177select count(*$0) from u;
2178"), @r"
2179 hover: column public.u.id int
2180 column public.u.b int
2181 ╭▸
2182 3 │ select count(*) from u;
2183 ╰╴ ─ hover
2184 ");
2185 }
2186
2187 #[test]
2188 fn hover_on_insert_table() {
2189 assert_snapshot!(check_hover("
2190create table users(id int, email text);
2191insert into users$0(id, email) values (1, 'test');
2192"), @r"
2193 hover: table public.users(id int, email text)
2194 ╭▸
2195 3 │ insert into users(id, email) values (1, 'test');
2196 ╰╴ ─ hover
2197 ");
2198 }
2199
2200 #[test]
2201 fn hover_on_insert_table_with_schema() {
2202 assert_snapshot!(check_hover("
2203create table public.users(id int, email text);
2204insert into public.users$0(id, email) values (1, 'test');
2205"), @r"
2206 hover: table public.users(id int, email text)
2207 ╭▸
2208 3 │ insert into public.users(id, email) values (1, 'test');
2209 ╰╴ ─ hover
2210 ");
2211 }
2212
2213 #[test]
2214 fn hover_on_insert_column() {
2215 assert_snapshot!(check_hover("
2216create table users(id int, email text);
2217insert into users(id$0, email) values (1, 'test');
2218"), @r"
2219 hover: column public.users.id int
2220 ╭▸
2221 3 │ insert into users(id, email) values (1, 'test');
2222 ╰╴ ─ hover
2223 ");
2224 }
2225
2226 #[test]
2227 fn hover_on_insert_column_second() {
2228 assert_snapshot!(check_hover("
2229create table users(id int, email text);
2230insert into users(id, email$0) values (1, 'test');
2231"), @r"
2232 hover: column public.users.email text
2233 ╭▸
2234 3 │ insert into users(id, email) values (1, 'test');
2235 ╰╴ ─ hover
2236 ");
2237 }
2238
2239 #[test]
2240 fn hover_on_insert_column_with_schema() {
2241 assert_snapshot!(check_hover("
2242create table public.users(id int, email text);
2243insert into public.users(email$0) values ('test');
2244"), @r"
2245 hover: column public.users.email text
2246 ╭▸
2247 3 │ insert into public.users(email) values ('test');
2248 ╰╴ ─ hover
2249 ");
2250 }
2251
2252 #[test]
2253 fn hover_on_delete_table() {
2254 assert_snapshot!(check_hover("
2255create table users(id int, email text);
2256delete from users$0 where id = 1;
2257"), @r"
2258 hover: table public.users(id int, email text)
2259 ╭▸
2260 3 │ delete from users where id = 1;
2261 ╰╴ ─ hover
2262 ");
2263 }
2264
2265 #[test]
2266 fn hover_on_delete_table_with_schema() {
2267 assert_snapshot!(check_hover("
2268create table public.users(id int, email text);
2269delete from public.users$0 where id = 1;
2270"), @r"
2271 hover: table public.users(id int, email text)
2272 ╭▸
2273 3 │ delete from public.users where id = 1;
2274 ╰╴ ─ hover
2275 ");
2276 }
2277
2278 #[test]
2279 fn hover_on_delete_where_column() {
2280 assert_snapshot!(check_hover("
2281create table users(id int, email text);
2282delete from users where id$0 = 1;
2283"), @r"
2284 hover: column public.users.id int
2285 ╭▸
2286 3 │ delete from users where id = 1;
2287 ╰╴ ─ hover
2288 ");
2289 }
2290
2291 #[test]
2292 fn hover_on_delete_where_column_second() {
2293 assert_snapshot!(check_hover("
2294create table users(id int, email text, active boolean);
2295delete from users where id = 1 and email$0 = 'test';
2296"), @r"
2297 hover: column public.users.email text
2298 ╭▸
2299 3 │ delete from users where id = 1 and email = 'test';
2300 ╰╴ ─ hover
2301 ");
2302 }
2303
2304 #[test]
2305 fn hover_on_delete_where_column_with_schema() {
2306 assert_snapshot!(check_hover("
2307create table public.users(id int, email text);
2308delete from public.users where email$0 = 'test';
2309"), @r"
2310 hover: column public.users.email text
2311 ╭▸
2312 3 │ delete from public.users where email = 'test';
2313 ╰╴ ─ hover
2314 ");
2315 }
2316
2317 #[test]
2318 fn hover_on_select_table_as_column() {
2319 assert_snapshot!(check_hover("
2320create table t(x bigint, y bigint);
2321select t$0 from t;
2322"), @r"
2323 hover: table public.t(x bigint, y bigint)
2324 ╭▸
2325 3 │ select t from t;
2326 ╰╴ ─ hover
2327 ");
2328 }
2329
2330 #[test]
2331 fn hover_on_select_table_as_column_with_schema() {
2332 assert_snapshot!(check_hover("
2333create table public.t(x bigint, y bigint);
2334select t$0 from public.t;
2335"), @r"
2336 hover: table public.t(x bigint, y bigint)
2337 ╭▸
2338 3 │ select t from public.t;
2339 ╰╴ ─ hover
2340 ");
2341 }
2342
2343 #[test]
2344 fn hover_on_select_table_as_column_with_search_path() {
2345 assert_snapshot!(check_hover("
2346set search_path to foo;
2347create table foo.users(id int, email text);
2348select users$0 from users;
2349"), @r"
2350 hover: table foo.users(id int, email text)
2351 ╭▸
2352 4 │ select users from users;
2353 ╰╴ ─ hover
2354 ");
2355 }
2356
2357 #[test]
2358 fn hover_on_select_column_with_same_name_as_table() {
2359 assert_snapshot!(check_hover("
2360create table t(t int);
2361select t$0 from t;
2362"), @r"
2363 hover: column public.t.t int
2364 ╭▸
2365 3 │ select t from t;
2366 ╰╴ ─ hover
2367 ");
2368 }
2369
2370 #[test]
2371 fn hover_on_create_schema() {
2372 assert_snapshot!(check_hover("
2373create schema foo$0;
2374"), @r"
2375 hover: schema foo
2376 ╭▸
2377 2 │ create schema foo;
2378 ╰╴ ─ hover
2379 ");
2380 }
2381
2382 #[test]
2383 fn hover_on_create_schema_authorization() {
2384 assert_snapshot!(check_hover("
2385create schema authorization foo$0;
2386"), @r"
2387 hover: schema foo
2388 ╭▸
2389 2 │ create schema authorization foo;
2390 ╰╴ ─ hover
2391 ");
2392 }
2393
2394 #[test]
2395 fn hover_on_drop_schema_authorization() {
2396 assert_snapshot!(check_hover("
2397create schema authorization foo;
2398drop schema foo$0;
2399"), @r"
2400 hover: schema foo
2401 ╭▸
2402 3 │ drop schema foo;
2403 ╰╴ ─ hover
2404 ");
2405 }
2406
2407 #[test]
2408 fn hover_on_drop_schema() {
2409 assert_snapshot!(check_hover("
2410create schema foo;
2411drop schema foo$0;
2412"), @r"
2413 hover: schema foo
2414 ╭▸
2415 3 │ drop schema foo;
2416 ╰╴ ─ hover
2417 ");
2418 }
2419
2420 #[test]
2421 fn hover_on_schema_after_definition() {
2422 assert_snapshot!(check_hover("
2423drop schema foo$0;
2424create schema foo;
2425"), @r"
2426 hover: schema foo
2427 ╭▸
2428 2 │ drop schema foo;
2429 ╰╴ ─ hover
2430 ");
2431 }
2432
2433 #[test]
2434 fn hover_on_cte_table() {
2435 assert_snapshot!(check_hover("
2436with t as (select 1 a)
2437select a from t$0;
2438"), @r"
2439 hover: with t as (select 1 a)
2440 ╭▸
2441 3 │ select a from t;
2442 ╰╴ ─ hover
2443 ");
2444 }
2445
2446 #[test]
2447 fn hover_on_cte_column() {
2448 assert_snapshot!(check_hover("
2449with t as (select 1 a)
2450select a$0 from t;
2451"), @r"
2452 hover: column t.a
2453 ╭▸
2454 3 │ select a from t;
2455 ╰╴ ─ hover
2456 ");
2457 }
2458
2459 #[test]
2460 fn hover_on_cte_with_multiple_columns() {
2461 assert_snapshot!(check_hover("
2462with t as (select 1 a, 2 b)
2463select b$0 from t;
2464"), @r"
2465 hover: column t.b
2466 ╭▸
2467 3 │ select b from t;
2468 ╰╴ ─ hover
2469 ");
2470 }
2471
2472 #[test]
2473 fn hover_on_cte_with_column_list() {
2474 assert_snapshot!(check_hover("
2475with t(a) as (select 1)
2476select a$0 from t;
2477"), @r"
2478 hover: column t.a
2479 ╭▸
2480 3 │ select a from t;
2481 ╰╴ ─ hover
2482 ");
2483 }
2484
2485 #[test]
2486 fn hover_on_nested_cte() {
2487 assert_snapshot!(check_hover("
2488with x as (select 1 a),
2489 y as (select a from x)
2490select a$0 from y;
2491"), @r"
2492 hover: column y.a
2493 ╭▸
2494 4 │ select a from y;
2495 ╰╴ ─ hover
2496 ");
2497 }
2498
2499 #[test]
2500 fn hover_on_cte_shadowing_table_with_star() {
2501 assert_snapshot!(check_hover("
2502create table t(a bigint);
2503with t as (select * from t)
2504select a$0 from t;
2505"), @r"
2506 hover: column public.t.a bigint
2507 ╭▸
2508 4 │ select a from t;
2509 ╰╴ ─ hover
2510 ");
2511 }
2512
2513 #[test]
2514 fn hover_on_cte_definition() {
2515 assert_snapshot!(check_hover("
2516with t$0 as (select 1 a)
2517select a from t;
2518"), @r"
2519 hover: with t as (select 1 a)
2520 ╭▸
2521 2 │ with t as (select 1 a)
2522 ╰╴ ─ hover
2523 ");
2524 }
2525
2526 #[test]
2527 fn hover_on_cte_values_column1() {
2528 assert_snapshot!(check_hover("
2529with t as (
2530 values (1, 2), (3, 4)
2531)
2532select column1$0, column2 from t;
2533"), @r"
2534 hover: column t.column1
2535 ╭▸
2536 5 │ select column1, column2 from t;
2537 ╰╴ ─ hover
2538 ");
2539 }
2540
2541 #[test]
2542 fn hover_on_cte_values_column2() {
2543 assert_snapshot!(check_hover("
2544with t as (
2545 values (1, 2), (3, 4)
2546)
2547select column1, column2$0 from t;
2548"), @r"
2549 hover: column t.column2
2550 ╭▸
2551 5 │ select column1, column2 from t;
2552 ╰╴ ─ hover
2553 ");
2554 }
2555
2556 #[test]
2557 fn hover_on_cte_values_single_column() {
2558 assert_snapshot!(check_hover("
2559with t as (
2560 values (1), (2), (3)
2561)
2562select column1$0 from t;
2563"), @r"
2564 hover: column t.column1
2565 ╭▸
2566 5 │ select column1 from t;
2567 ╰╴ ─ hover
2568 ");
2569 }
2570
2571 #[test]
2572 fn hover_on_cte_values_uppercase_column_names() {
2573 assert_snapshot!(check_hover("
2574with t as (
2575 values (1, 2), (3, 4)
2576)
2577select COLUMN1$0, COLUMN2 from t;
2578"), @r"
2579 hover: column t.column1
2580 ╭▸
2581 5 │ select COLUMN1, COLUMN2 from t;
2582 ╰╴ ─ hover
2583 ");
2584 }
2585
2586 #[test]
2587 fn hover_on_cte_qualified_star() {
2588 assert_snapshot!(check_hover("
2589with u as (select 1 id, 2 b)
2590select u.*$0 from u;
2591"), @r"
2592 hover: column u.id
2593 column u.b
2594 ╭▸
2595 3 │ select u.* from u;
2596 ╰╴ ─ hover
2597 ");
2598 }
2599
2600 #[test]
2601 fn hover_on_cte_values_qualified_star() {
2602 assert_snapshot!(check_hover("
2603with t as (values (1, 2), (3, 4))
2604select t.*$0 from t;
2605"), @r"
2606 hover: column t.column1
2607 column t.column2
2608 ╭▸
2609 3 │ select t.* from t;
2610 ╰╴ ─ hover
2611 ");
2612 }
2613
2614 #[test]
2615 fn hover_on_star_with_subquery_from_cte() {
2616 assert_snapshot!(check_hover("
2617with u as (select 1 id, 2 b)
2618select *$0 from (select *, *, * from u);
2619"), @r"
2620 hover: column u.id
2621 column u.b
2622 column u.id
2623 column u.b
2624 column u.id
2625 column u.b
2626 ╭▸
2627 3 │ select * from (select *, *, * from u);
2628 ╰╴ ─ hover
2629 ");
2630 }
2631
2632 #[test]
2633 fn hover_on_star_with_subquery_from_table() {
2634 assert_snapshot!(check_hover("
2635create table t(a int, b int);
2636select *$0 from (select a from t);
2637"), @r"
2638 hover: column public.t.a int
2639 ╭▸
2640 3 │ select * from (select a from t);
2641 ╰╴ ─ hover
2642 ");
2643 }
2644
2645 #[test]
2646 fn hover_on_view_qualified_star() {
2647 assert_snapshot!(check_hover("
2648create view v as select 1 id, 2 b;
2649select v.*$0 from v;
2650"), @r"
2651 hover: column public.v.id
2652 column public.v.b
2653 ╭▸
2654 3 │ select v.* from v;
2655 ╰╴ ─ hover
2656 ");
2657 }
2658
2659 #[test]
2660 fn hover_on_drop_procedure() {
2661 assert_snapshot!(check_hover("
2662create procedure foo() language sql as $$ select 1 $$;
2663drop procedure foo$0();
2664"), @r"
2665 hover: procedure public.foo()
2666 ╭▸
2667 3 │ drop procedure foo();
2668 ╰╴ ─ hover
2669 ");
2670 }
2671
2672 #[test]
2673 fn hover_on_drop_procedure_with_schema() {
2674 assert_snapshot!(check_hover("
2675create procedure myschema.foo() language sql as $$ select 1 $$;
2676drop procedure myschema.foo$0();
2677"), @r"
2678 hover: procedure myschema.foo()
2679 ╭▸
2680 3 │ drop procedure myschema.foo();
2681 ╰╴ ─ hover
2682 ");
2683 }
2684
2685 #[test]
2686 fn hover_on_create_procedure_definition() {
2687 assert_snapshot!(check_hover("
2688create procedure foo$0() language sql as $$ select 1 $$;
2689"), @r"
2690 hover: procedure public.foo()
2691 ╭▸
2692 2 │ create procedure foo() language sql as $$ select 1 $$;
2693 ╰╴ ─ hover
2694 ");
2695 }
2696
2697 #[test]
2698 fn hover_on_create_procedure_with_explicit_schema() {
2699 assert_snapshot!(check_hover("
2700create procedure myschema.foo$0() language sql as $$ select 1 $$;
2701"), @r"
2702 hover: procedure myschema.foo()
2703 ╭▸
2704 2 │ create procedure myschema.foo() language sql as $$ select 1 $$;
2705 ╰╴ ─ hover
2706 ");
2707 }
2708
2709 #[test]
2710 fn hover_on_drop_procedure_with_search_path() {
2711 assert_snapshot!(check_hover(r#"
2712set search_path to myschema;
2713create procedure foo() language sql as $$ select 1 $$;
2714drop procedure foo$0();
2715"#), @r"
2716 hover: procedure myschema.foo()
2717 ╭▸
2718 4 │ drop procedure foo();
2719 ╰╴ ─ hover
2720 ");
2721 }
2722
2723 #[test]
2724 fn hover_on_drop_procedure_overloaded() {
2725 assert_snapshot!(check_hover("
2726create procedure add(complex) language sql as $$ select null $$;
2727create procedure add(bigint) language sql as $$ select 1 $$;
2728drop procedure add$0(complex);
2729"), @r"
2730 hover: procedure public.add(complex)
2731 ╭▸
2732 4 │ drop procedure add(complex);
2733 ╰╴ ─ hover
2734 ");
2735 }
2736
2737 #[test]
2738 fn hover_on_drop_procedure_second_overload() {
2739 assert_snapshot!(check_hover("
2740create procedure add(complex) language sql as $$ select null $$;
2741create procedure add(bigint) language sql as $$ select 1 $$;
2742drop procedure add$0(bigint);
2743"), @r"
2744 hover: procedure public.add(bigint)
2745 ╭▸
2746 4 │ drop procedure add(bigint);
2747 ╰╴ ─ hover
2748 ");
2749 }
2750
2751 #[test]
2752 fn hover_on_call_procedure() {
2753 assert_snapshot!(check_hover("
2754create procedure foo() language sql as $$ select 1 $$;
2755call foo$0();
2756"), @r"
2757 hover: procedure public.foo()
2758 ╭▸
2759 3 │ call foo();
2760 ╰╴ ─ hover
2761 ");
2762 }
2763
2764 #[test]
2765 fn hover_on_call_procedure_with_schema() {
2766 assert_snapshot!(check_hover("
2767create procedure public.foo() language sql as $$ select 1 $$;
2768call public.foo$0();
2769"), @r"
2770 hover: procedure public.foo()
2771 ╭▸
2772 3 │ call public.foo();
2773 ╰╴ ─ hover
2774 ");
2775 }
2776
2777 #[test]
2778 fn hover_on_call_procedure_with_search_path() {
2779 assert_snapshot!(check_hover(r#"
2780set search_path to myschema;
2781create procedure foo() language sql as $$ select 1 $$;
2782call foo$0();
2783"#), @r"
2784 hover: procedure myschema.foo()
2785 ╭▸
2786 4 │ call foo();
2787 ╰╴ ─ hover
2788 ");
2789 }
2790
2791 #[test]
2792 fn hover_on_call_procedure_with_params() {
2793 assert_snapshot!(check_hover("
2794create procedure add(a int, b int) language sql as $$ select a + b $$;
2795call add$0(1, 2);
2796"), @r"
2797 hover: procedure public.add(a int, b int)
2798 ╭▸
2799 3 │ call add(1, 2);
2800 ╰╴ ─ hover
2801 ");
2802 }
2803
2804 #[test]
2805 fn hover_on_drop_routine_function() {
2806 assert_snapshot!(check_hover("
2807create function foo() returns int as $$ select 1 $$ language sql;
2808drop routine foo$0();
2809"), @r"
2810 hover: function public.foo() returns int
2811 ╭▸
2812 3 │ drop routine foo();
2813 ╰╴ ─ hover
2814 ");
2815 }
2816
2817 #[test]
2818 fn hover_on_drop_routine_aggregate() {
2819 assert_snapshot!(check_hover("
2820create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
2821drop routine myavg$0(int);
2822"), @r"
2823 hover: aggregate public.myavg(int)
2824 ╭▸
2825 3 │ drop routine myavg(int);
2826 ╰╴ ─ hover
2827 ");
2828 }
2829
2830 #[test]
2831 fn hover_on_drop_routine_procedure() {
2832 assert_snapshot!(check_hover("
2833create procedure foo() language sql as $$ select 1 $$;
2834drop routine foo$0();
2835"), @r"
2836 hover: procedure public.foo()
2837 ╭▸
2838 3 │ drop routine foo();
2839 ╰╴ ─ hover
2840 ");
2841 }
2842
2843 #[test]
2844 fn hover_on_drop_routine_with_schema() {
2845 assert_snapshot!(check_hover("
2846set search_path to public;
2847create function foo() returns int as $$ select 1 $$ language sql;
2848drop routine public.foo$0();
2849"), @r"
2850 hover: function public.foo() returns int
2851 ╭▸
2852 4 │ drop routine public.foo();
2853 ╰╴ ─ hover
2854 ");
2855 }
2856
2857 #[test]
2858 fn hover_on_drop_routine_with_search_path() {
2859 assert_snapshot!(check_hover(r#"
2860set search_path to myschema;
2861create function foo() returns int as $$ select 1 $$ language sql;
2862drop routine foo$0();
2863"#), @r"
2864 hover: function myschema.foo() returns int
2865 ╭▸
2866 4 │ drop routine foo();
2867 ╰╴ ─ hover
2868 ");
2869 }
2870
2871 #[test]
2872 fn hover_on_drop_routine_overloaded() {
2873 assert_snapshot!(check_hover("
2874create function add(complex) returns complex as $$ select null $$ language sql;
2875create function add(bigint) returns bigint as $$ select 1 $$ language sql;
2876drop routine add$0(complex);
2877"), @r"
2878 hover: function public.add(complex) returns complex
2879 ╭▸
2880 4 │ drop routine add(complex);
2881 ╰╴ ─ hover
2882 ");
2883 }
2884
2885 #[test]
2886 fn hover_on_drop_routine_prefers_function_over_procedure() {
2887 assert_snapshot!(check_hover("
2888create function foo() returns int as $$ select 1 $$ language sql;
2889create procedure foo() language sql as $$ select 1 $$;
2890drop routine foo$0();
2891"), @r"
2892 hover: function public.foo() returns int
2893 ╭▸
2894 4 │ drop routine foo();
2895 ╰╴ ─ hover
2896 ");
2897 }
2898
2899 #[test]
2900 fn hover_on_drop_routine_prefers_aggregate_over_procedure() {
2901 assert_snapshot!(check_hover("
2902create aggregate foo(int) (sfunc = int4_avg_accum, stype = _int8);
2903create procedure foo(int) language sql as $$ select 1 $$;
2904drop routine foo$0(int);
2905"), @r"
2906 hover: aggregate public.foo(int)
2907 ╭▸
2908 4 │ drop routine foo(int);
2909 ╰╴ ─ hover
2910 ");
2911 }
2912
2913 #[test]
2914 fn hover_on_update_table() {
2915 assert_snapshot!(check_hover("
2916create table users(id int, email text);
2917update users$0 set email = 'new@example.com';
2918"), @r"
2919 hover: table public.users(id int, email text)
2920 ╭▸
2921 3 │ update users set email = 'new@example.com';
2922 ╰╴ ─ hover
2923 ");
2924 }
2925
2926 #[test]
2927 fn hover_on_update_table_with_schema() {
2928 assert_snapshot!(check_hover("
2929create table public.users(id int, email text);
2930update public.users$0 set email = 'new@example.com';
2931"), @r"
2932 hover: table public.users(id int, email text)
2933 ╭▸
2934 3 │ update public.users set email = 'new@example.com';
2935 ╰╴ ─ hover
2936 ");
2937 }
2938
2939 #[test]
2940 fn hover_on_update_set_column() {
2941 assert_snapshot!(check_hover("
2942create table users(id int, email text);
2943update users set email$0 = 'new@example.com' where id = 1;
2944"), @r"
2945 hover: column public.users.email text
2946 ╭▸
2947 3 │ update users set email = 'new@example.com' where id = 1;
2948 ╰╴ ─ hover
2949 ");
2950 }
2951
2952 #[test]
2953 fn hover_on_update_set_column_with_schema() {
2954 assert_snapshot!(check_hover("
2955create table public.users(id int, email text);
2956update public.users set email$0 = 'new@example.com' where id = 1;
2957"), @r"
2958 hover: column public.users.email text
2959 ╭▸
2960 3 │ update public.users set email = 'new@example.com' where id = 1;
2961 ╰╴ ─ hover
2962 ");
2963 }
2964
2965 #[test]
2966 fn hover_on_update_where_column() {
2967 assert_snapshot!(check_hover("
2968create table users(id int, email text);
2969update users set email = 'new@example.com' where id$0 = 1;
2970"), @r"
2971 hover: column public.users.id int
2972 ╭▸
2973 3 │ update users set email = 'new@example.com' where id = 1;
2974 ╰╴ ─ hover
2975 ");
2976 }
2977
2978 #[test]
2979 fn hover_on_update_where_column_with_schema() {
2980 assert_snapshot!(check_hover("
2981create table public.users(id int, email text);
2982update public.users set email = 'new@example.com' where id$0 = 1;
2983"), @r"
2984 hover: column public.users.id int
2985 ╭▸
2986 3 │ update public.users set email = 'new@example.com' where id = 1;
2987 ╰╴ ─ hover
2988 ");
2989 }
2990
2991 #[test]
2992 fn hover_on_update_from_table() {
2993 assert_snapshot!(check_hover("
2994create table users(id int, email text);
2995create table messages(id int, user_id int, email text);
2996update users set email = messages.email from messages$0 where users.id = messages.user_id;
2997"), @r"
2998 hover: table public.messages(id int, user_id int, email text)
2999 ╭▸
3000 4 │ update users set email = messages.email from messages where users.id = messages.user_id;
3001 ╰╴ ─ hover
3002 ");
3003 }
3004
3005 #[test]
3006 fn hover_on_update_from_table_with_schema() {
3007 assert_snapshot!(check_hover("
3008create table users(id int, email text);
3009create table public.messages(id int, user_id int, email text);
3010update users set email = messages.email from public.messages$0 where users.id = messages.user_id;
3011"), @r"
3012 hover: table public.messages(id int, user_id int, email text)
3013 ╭▸
3014 4 │ update users set email = messages.email from public.messages where users.id = messages.user_id;
3015 ╰╴ ─ hover
3016 ");
3017 }
3018
3019 #[test]
3020 fn hover_on_update_with_cte_table() {
3021 assert_snapshot!(check_hover("
3022create table users(id int, email text);
3023with new_data as (
3024 select 1 as id, 'new@example.com' as email
3025)
3026update users set email = new_data.email from new_data$0 where users.id = new_data.id;
3027"), @r"
3028 hover: with new_data as (select 1 as id, 'new@example.com' as email)
3029 ╭▸
3030 6 │ update users set email = new_data.email from new_data where users.id = new_data.id;
3031 ╰╴ ─ hover
3032 ");
3033 }
3034
3035 #[test]
3036 fn hover_on_update_with_cte_column_in_set() {
3037 assert_snapshot!(check_hover("
3038create table users(id int, email text);
3039with new_data as (
3040 select 1 as id, 'new@example.com' as email
3041)
3042update users set email = new_data.email$0 from new_data where users.id = new_data.id;
3043"), @r"
3044 hover: column new_data.email
3045 ╭▸
3046 6 │ update users set email = new_data.email from new_data where users.id = new_data.id;
3047 ╰╴ ─ hover
3048 ");
3049 }
3050
3051 #[test]
3052 fn hover_on_update_with_cte_column_in_where() {
3053 assert_snapshot!(check_hover("
3054create table users(id int, email text);
3055with new_data as (
3056 select 1 as id, 'new@example.com' as email
3057)
3058update users set email = new_data.email from new_data where new_data.id$0 = users.id;
3059"), @r"
3060 hover: column new_data.id
3061 ╭▸
3062 6 │ update users set email = new_data.email from new_data where new_data.id = users.id;
3063 ╰╴ ─ hover
3064 ");
3065 }
3066
3067 #[test]
3068 fn hover_on_create_view_definition() {
3069 assert_snapshot!(check_hover("
3070create view v$0 as select 1;
3071"), @r"
3072 hover: view public.v as select 1
3073 ╭▸
3074 2 │ create view v as select 1;
3075 ╰╴ ─ hover
3076 ");
3077 }
3078
3079 #[test]
3080 fn hover_on_create_view_definition_with_schema() {
3081 assert_snapshot!(check_hover("
3082create view myschema.v$0 as select 1;
3083"), @r"
3084 hover: view myschema.v as select 1
3085 ╭▸
3086 2 │ create view myschema.v as select 1;
3087 ╰╴ ─ hover
3088 ");
3089 }
3090
3091 #[test]
3092 fn hover_on_create_temp_view_definition() {
3093 assert_snapshot!(check_hover("
3094create temp view v$0 as select 1;
3095"), @r"
3096 hover: view pg_temp.v as select 1
3097 ╭▸
3098 2 │ create temp view v as select 1;
3099 ╰╴ ─ hover
3100 ");
3101 }
3102
3103 #[test]
3104 fn hover_on_create_view_with_column_list() {
3105 assert_snapshot!(check_hover("
3106create view v(col1$0) as select 1;
3107"), @r"
3108 hover: column public.v.col1
3109 ╭▸
3110 2 │ create view v(col1) as select 1;
3111 ╰╴ ─ hover
3112 ");
3113 }
3114
3115 #[test]
3116 fn hover_on_select_from_view() {
3117 assert_snapshot!(check_hover("
3118create view v as select 1;
3119select * from v$0;
3120"), @r"
3121 hover: view public.v as select 1
3122 ╭▸
3123 3 │ select * from v;
3124 ╰╴ ─ hover
3125 ");
3126 }
3127
3128 #[test]
3129 fn hover_on_select_column_from_view_column_list() {
3130 assert_snapshot!(check_hover("
3131create view v(a) as select 1;
3132select a$0 from v;
3133"), @r"
3134 hover: column public.v.a
3135 ╭▸
3136 3 │ select a from v;
3137 ╰╴ ─ hover
3138 ");
3139 }
3140
3141 #[test]
3142 fn hover_on_select_column_from_view_column_list_overrides_target() {
3143 assert_snapshot!(check_hover("
3144create view v(a) as select 1, 2 b;
3145select a, b$0 from v;
3146"), @r"
3147 hover: column public.v.b
3148 ╭▸
3149 3 │ select a, b from v;
3150 ╰╴ ─ hover
3151 ");
3152 }
3153
3154 #[test]
3155 fn hover_on_select_column_from_view_target_list() {
3156 assert_snapshot!(check_hover("
3157create view v as select 1 a, 2 b;
3158select a$0, b from v;
3159"), @r"
3160 hover: column public.v.a
3161 ╭▸
3162 3 │ select a, b from v;
3163 ╰╴ ─ hover
3164 ");
3165 }
3166
3167 #[test]
3168 fn hover_on_select_from_view_with_schema() {
3169 assert_snapshot!(check_hover("
3170create view myschema.v as select 1;
3171select * from myschema.v$0;
3172"), @r"
3173 hover: view myschema.v as select 1
3174 ╭▸
3175 3 │ select * from myschema.v;
3176 ╰╴ ─ hover
3177 ");
3178 }
3179
3180 #[test]
3181 fn hover_on_drop_view() {
3182 assert_snapshot!(check_hover("
3183create view v as select 1;
3184drop view v$0;
3185"), @r"
3186 hover: view public.v as select 1
3187 ╭▸
3188 3 │ drop view v;
3189 ╰╴ ─ hover
3190 ");
3191 }
3192
3193 #[test]
3194 fn hover_composite_type_field() {
3195 assert_snapshot!(check_hover("
3196create type person_info as (name varchar(50), age int);
3197with team as (
3198 select 1 as id, ('Alice', 30)::person_info as member
3199)
3200select (member).name$0, (member).age from team;
3201"), @r"
3202 hover: field public.person_info.name varchar(50)
3203 ╭▸
3204 6 │ select (member).name, (member).age from team;
3205 ╰╴ ─ hover
3206 ");
3207 }
3208
3209 #[test]
3210 fn hover_composite_type_field_age() {
3211 assert_snapshot!(check_hover("
3212create type person_info as (name varchar(50), age int);
3213with team as (
3214 select 1 as id, ('Alice', 30)::person_info as member
3215)
3216select (member).name, (member).age$0 from team;
3217"), @r"
3218 hover: field public.person_info.age int
3219 ╭▸
3220 6 │ select (member).name, (member).age from team;
3221 ╰╴ ─ hover
3222 ");
3223 }
3224
3225 #[test]
3226 fn hover_composite_type_field_nested_parens() {
3227 assert_snapshot!(check_hover("
3228create type person_info as (name varchar(50), age int);
3229with team as (
3230 select 1 as id, ('Alice', 30)::person_info as member
3231)
3232select ((((member))).name$0) from team;
3233"), @r"
3234 hover: field public.person_info.name varchar(50)
3235 ╭▸
3236 6 │ select ((((member))).name) from team;
3237 ╰╴ ─ hover
3238 ");
3239 }
3240
3241 #[test]
3242 fn hover_on_join_using_column() {
3243 assert_snapshot!(check_hover("
3244create table t(id int);
3245create table u(id int);
3246select * from t join u using (id$0);
3247"), @r"
3248 hover: column public.t.id int
3249 column public.u.id int
3250 ╭▸
3251 4 │ select * from t join u using (id);
3252 ╰╴ ─ hover
3253 ");
3254 }
3255
3256 #[test]
3257 fn hover_on_truncate_table() {
3258 assert_snapshot!(check_hover("
3259create table users(id int, email text);
3260truncate table users$0;
3261"), @r"
3262 hover: table public.users(id int, email text)
3263 ╭▸
3264 3 │ truncate table users;
3265 ╰╴ ─ hover
3266 ");
3267 }
3268
3269 #[test]
3270 fn hover_on_truncate_table_without_table_keyword() {
3271 assert_snapshot!(check_hover("
3272create table users(id int, email text);
3273truncate users$0;
3274"), @r"
3275 hover: table public.users(id int, email text)
3276 ╭▸
3277 3 │ truncate users;
3278 ╰╴ ─ hover
3279 ");
3280 }
3281
3282 #[test]
3283 fn hover_on_lock_table() {
3284 assert_snapshot!(check_hover("
3285create table users(id int, email text);
3286lock table users$0;
3287"), @r"
3288 hover: table public.users(id int, email text)
3289 ╭▸
3290 3 │ lock table users;
3291 ╰╴ ─ hover
3292 ");
3293 }
3294
3295 #[test]
3296 fn hover_on_lock_table_without_table_keyword() {
3297 assert_snapshot!(check_hover("
3298create table users(id int, email text);
3299lock users$0;
3300"), @r"
3301 hover: table public.users(id int, email text)
3302 ╭▸
3303 3 │ lock users;
3304 ╰╴ ─ hover
3305 ");
3306 }
3307
3308 #[test]
3309 fn hover_on_vacuum_table() {
3310 assert_snapshot!(check_hover("
3311create table users(id int, email text);
3312vacuum users$0;
3313"), @r"
3314 hover: table public.users(id int, email text)
3315 ╭▸
3316 3 │ vacuum users;
3317 ╰╴ ─ hover
3318 ");
3319 }
3320
3321 #[test]
3322 fn hover_on_vacuum_with_analyze() {
3323 assert_snapshot!(check_hover("
3324create table users(id int, email text);
3325vacuum analyze users$0;
3326"), @r"
3327 hover: table public.users(id int, email text)
3328 ╭▸
3329 3 │ vacuum analyze users;
3330 ╰╴ ─ hover
3331 ");
3332 }
3333
3334 #[test]
3335 fn hover_on_alter_table() {
3336 assert_snapshot!(check_hover("
3337create table users(id int, email text);
3338alter table users$0 alter email set not null;
3339"), @r"
3340 hover: table public.users(id int, email text)
3341 ╭▸
3342 3 │ alter table users alter email set not null;
3343 ╰╴ ─ hover
3344 ");
3345 }
3346
3347 #[test]
3348 fn hover_on_alter_table_column() {
3349 assert_snapshot!(check_hover("
3350create table users(id int, email text);
3351alter table users alter email$0 set not null;
3352"), @r"
3353 hover: column public.users.email text
3354 ╭▸
3355 3 │ alter table users alter email set not null;
3356 ╰╴ ─ hover
3357 ");
3358 }
3359
3360 #[test]
3361 fn hover_on_refresh_materialized_view() {
3362 assert_snapshot!(check_hover("
3363create materialized view mv as select 1;
3364refresh materialized view mv$0;
3365"), @r"
3366 hover: materialized view public.mv as select 1
3367 ╭▸
3368 3 │ refresh materialized view mv;
3369 ╰╴ ─ hover
3370 ");
3371 }
3372
3373 #[test]
3374 fn hover_on_reindex_table() {
3375 assert_snapshot!(check_hover("
3376create table users(id int);
3377reindex table users$0;
3378"), @r"
3379 hover: table public.users(id int)
3380 ╭▸
3381 3 │ reindex table users;
3382 ╰╴ ─ hover
3383 ");
3384 }
3385
3386 #[test]
3387 fn hover_on_reindex_index() {
3388 assert_snapshot!(check_hover("
3389create table t(c int);
3390create index idx on t(c);
3391reindex index idx$0;
3392"), @r"
3393 hover: index public.idx on public.t(c)
3394 ╭▸
3395 4 │ reindex index idx;
3396 ╰╴ ─ hover
3397 ");
3398 }
3399
3400 #[test]
3401 fn hover_merge_returning_star_from_cte() {
3402 assert_snapshot!(check_hover("
3403create table t(a int, b int);
3404with u(x, y) as (
3405 select 1, 2
3406),
3407merged as (
3408 merge into t
3409 using u
3410 on t.a = u.x
3411 when matched then
3412 do nothing
3413 when not matched then
3414 do nothing
3415 returning a as x, b as y
3416)
3417select *$0 from merged;
3418"), @r"
3419 hover: column merged.x
3420 column merged.y
3421 ╭▸
3422 16 │ select * from merged;
3423 ╰╴ ─ hover
3424 ");
3425 }
3426}