Skip to content

Commit 26f8f83

Browse files
authored
ide: goto def with column function calling in policy stmt exprs (#888)
1 parent ba3ef1f commit 26f8f83

File tree

4 files changed

+131
-31
lines changed

4 files changed

+131
-31
lines changed

crates/squawk_ide/src/classify.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,15 @@ pub(crate) fn classify_name_ref(name_ref: &ast::NameRef) -> Option<NameRefClass>
356356
return Some(NameRefClass::SelectQualifiedColumnTable);
357357
}
358358
}
359+
if ast::CreatePolicy::can_cast(ancestor.kind())
360+
|| ast::AlterPolicy::can_cast(ancestor.kind())
361+
{
362+
if is_base_of_outer_field_expr {
363+
return Some(NameRefClass::PolicyQualifiedColumnTable);
364+
} else {
365+
return Some(NameRefClass::PolicyColumn);
366+
}
367+
}
359368
}
360369
}
361370

crates/squawk_ide/src/goto_definition.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,25 @@ create policy p on t
615615
");
616616
}
617617

618+
#[test]
619+
fn goto_create_policy_field_style_function_call() {
620+
assert_snapshot!(goto("
621+
create table t(c int);
622+
create function x(t) returns int8
623+
as 'select 1'
624+
language sql;
625+
create policy p on t
626+
with check (t.c > 1 and t.x$0 > 0);
627+
"), @r"
628+
╭▸
629+
3 │ create function x(t) returns int8
630+
│ ─ 2. destination
631+
632+
7 │ with check (t.c > 1 and t.x > 0);
633+
╰╴ ─ 1. source
634+
");
635+
}
636+
618637
#[test]
619638
fn goto_alter_policy_qualified_column_table() {
620639
assert_snapshot!(goto("
@@ -631,6 +650,56 @@ alter policy p on t
631650
");
632651
}
633652

653+
#[test]
654+
fn goto_alter_policy_qualified_column() {
655+
assert_snapshot!(goto("
656+
create table t(c int, d int);
657+
alter policy p on t
658+
with check (t.c$0 > d);
659+
"), @r"
660+
╭▸
661+
2 │ create table t(c int, d int);
662+
│ ─ 2. destination
663+
3 │ alter policy p on t
664+
4 │ with check (t.c > d);
665+
╰╴ ─ 1. source
666+
");
667+
}
668+
669+
#[test]
670+
fn goto_create_policy_schema_qualified_table() {
671+
assert_snapshot!(goto("
672+
create schema foo;
673+
create table foo.t(c int);
674+
create policy p on foo.t
675+
with check (foo.t$0.c > 1);
676+
"), @r"
677+
╭▸
678+
3 │ create table foo.t(c int);
679+
│ ─ 2. destination
680+
4 │ create policy p on foo.t
681+
5 │ with check (foo.t.c > 1);
682+
╰╴ ─ 1. source
683+
");
684+
}
685+
686+
#[test]
687+
fn goto_create_policy_unqualified_table_with_schema_on_table() {
688+
assert_snapshot!(goto("
689+
create schema foo;
690+
create table foo.t(c int);
691+
create policy p on foo.t
692+
with check (t$0.c > 1);
693+
"), @r"
694+
╭▸
695+
3 │ create table foo.t(c int);
696+
│ ─ 2. destination
697+
4 │ create policy p on foo.t
698+
5 │ with check (t.c > 1);
699+
╰╴ ─ 1. source
700+
");
701+
}
702+
634703
#[test]
635704
fn goto_drop_event_trigger() {
636705
assert_snapshot!(goto("

crates/squawk_ide/src/hover.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
5757
| NameRefClass::MergeWhenColumn
5858
| NameRefClass::MergeOnColumn
5959
| NameRefClass::CheckConstraintColumn
60-
| NameRefClass::PolicyColumn
6160
| NameRefClass::GeneratedColumn
6261
| NameRefClass::UniqueConstraintColumn
6362
| NameRefClass::PrimaryKeyConstraintColumn
@@ -78,7 +77,9 @@ pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
7877
NameRefClass::CompositeTypeField => {
7978
return hover_composite_type_field(root, &name_ref, &binder);
8079
}
81-
NameRefClass::SelectColumn | NameRefClass::SelectQualifiedColumn => {
80+
NameRefClass::SelectColumn
81+
| NameRefClass::SelectQualifiedColumn
82+
| NameRefClass::PolicyColumn => {
8283
// Try hover as column first
8384
if let Some(result) = hover_column(root, &name_ref, &binder) {
8485
return Some(result);

crates/squawk_ide/src/resolve.rs

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,7 @@ pub(crate) fn resolve_name_ref_ptrs(
285285
None
286286
}
287287
})?;
288-
let column_name = Name::from_node(name_ref);
289-
resolve_column_for_path(binder, root, &on_table_path, column_name)
288+
resolve_policy_column_ptr(binder, root, &on_table_path, name_ref)
290289
.map(|ptr| smallvec![ptr])
291290
}
292291
NameRefClass::PolicyQualifiedColumnTable => {
@@ -844,17 +843,43 @@ fn resolve_column_for_path(
844843
let schema = extract_schema_name(path);
845844
let position = path.syntax().text_range().start();
846845

847-
if let Some(resolved) = resolve_table_name(binder, root, &table_name, &schema, position) {
848-
match resolved {
849-
ResolvedTableName::View(create_view) => {
850-
find_column_in_create_view(&create_view, &column_name)
846+
let resolved = resolve_table_name(binder, root, &table_name, &schema, position)?;
847+
match resolved {
848+
ResolvedTableName::View(create_view) => {
849+
find_column_in_create_view(&create_view, &column_name)
850+
}
851+
ResolvedTableName::Table(create_table_like) => {
852+
find_column_in_create_table(binder, root, &create_table_like, &column_name)
853+
}
854+
}
855+
}
856+
857+
fn resolve_policy_column_ptr(
858+
binder: &Binder,
859+
root: &SyntaxNode,
860+
on_table_path: &ast::Path,
861+
column_name_ref: &ast::NameRef,
862+
) -> Option<SyntaxNodePtr> {
863+
let column_name = Name::from_node(column_name_ref);
864+
let (table_name, schema) = extract_table_schema_from_path(on_table_path)?;
865+
let position = column_name_ref.syntax().text_range().start();
866+
867+
let resolved = resolve_table_name(binder, root, &table_name, &schema, position)?;
868+
match resolved {
869+
ResolvedTableName::View(create_view) => {
870+
if let Some(ptr) = find_column_in_create_view(&create_view, &column_name) {
871+
return Some(ptr);
851872
}
852-
ResolvedTableName::Table(create_table_like) => {
873+
resolve_function(binder, &column_name, &schema, None, position)
874+
}
875+
ResolvedTableName::Table(create_table_like) => {
876+
if let Some(ptr) =
853877
find_column_in_create_table(binder, root, &create_table_like, &column_name)
878+
{
879+
return Some(ptr);
854880
}
881+
resolve_function(binder, &column_name, &schema, None, position)
855882
}
856-
} else {
857-
None
858883
}
859884
}
860885

@@ -1199,30 +1224,26 @@ fn resolve_select_qualified_column_ptr(
11991224
}
12001225
}
12011226

1202-
if let Some(resolved) = resolve_table_name(binder, root, &table_name, &schema, position) {
1203-
match resolved {
1204-
ResolvedTableName::View(create_view) => {
1205-
if let Some(ptr) = find_column_in_create_view(&create_view, &column_name) {
1206-
return Some(ptr);
1207-
}
1208-
1209-
return resolve_function(binder, &column_name, &schema, None, position);
1227+
let resolved = resolve_table_name(binder, root, &table_name, &schema, position)?;
1228+
match resolved {
1229+
ResolvedTableName::View(create_view) => {
1230+
if let Some(ptr) = find_column_in_create_view(&create_view, &column_name) {
1231+
return Some(ptr);
12101232
}
1211-
ResolvedTableName::Table(create_table_like) => {
1212-
// 1. Try to find a matching column (columns take precedence)
1213-
if let Some(ptr) =
1214-
find_column_in_create_table(binder, root, &create_table_like, &column_name)
1215-
{
1216-
return Some(ptr);
1217-
}
1218-
// 2. No column found, check for field-style function call
1219-
// e.g., select t.b from t where b is a function that takes t as an argument
1220-
return resolve_function(binder, &column_name, &schema, None, position);
1233+
return resolve_function(binder, &column_name, &schema, None, position);
1234+
}
1235+
ResolvedTableName::Table(create_table_like) => {
1236+
// 1. Try to find a matching column (columns take precedence)
1237+
if let Some(ptr) =
1238+
find_column_in_create_table(binder, root, &create_table_like, &column_name)
1239+
{
1240+
return Some(ptr);
12211241
}
1242+
// 2. No column found, check for field-style function call
1243+
// e.g., select t.b from t where b is a function that takes t as an argument
1244+
return resolve_function(binder, &column_name, &schema, None, position);
12221245
}
12231246
}
1224-
1225-
None
12261247
}
12271248

12281249
enum ResolvedTableName {

0 commit comments

Comments
 (0)