Skip to content

Commit 4f48877

Browse files
authored
ide: goto def create temp table (#737)
1 parent 706257c commit 4f48877

File tree

4 files changed

+112
-38
lines changed

4 files changed

+112
-38
lines changed

crates/squawk_ide/src/binder.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ fn bind_create_table(b: &mut Binder, create_table: ast::CreateTable) {
5858
return;
5959
};
6060
let name_ptr = path_to_ptr(&path);
61-
let schema = schema_name(&path);
61+
let is_temp = create_table.temp_token().is_some() || create_table.temporary_token().is_some();
62+
let schema = schema_name(&path, is_temp);
6263

6364
let table_id = b.symbols.alloc(Symbol {
6465
kind: SymbolKind::Table,
@@ -95,21 +96,20 @@ fn path_to_ptr(path: &ast::Path) -> SyntaxNodePtr {
9596
SyntaxNodePtr::new(path.syntax())
9697
}
9798

98-
fn schema_name(path: &ast::Path) -> Schema {
99-
let Some(qualifier) = path.qualifier() else {
100-
return Schema::Public;
101-
};
102-
let Some(segment) = qualifier.segment() else {
103-
return Schema::Public;
99+
fn schema_name(path: &ast::Path, is_temp: bool) -> Schema {
100+
let default_schema = if is_temp { "pg_temp" } else { "public" };
101+
102+
let Some(segment) = path.qualifier().and_then(|q| q.segment()) else {
103+
return Schema::new(default_schema);
104104
};
105105

106106
let schema_name = if let Some(name) = segment.name() {
107107
Name::new(name.syntax().text().to_string())
108108
} else if let Some(name_ref) = segment.name_ref() {
109109
Name::new(name_ref.syntax().text().to_string())
110110
} else {
111-
return Schema::Public;
111+
return Schema::new(default_schema);
112112
};
113113

114-
Schema::from_name(schema_name)
114+
Schema(schema_name)
115115
}

crates/squawk_ide/src/goto_definition.rs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,81 @@ create table t();
259259
drop table foo.t$0;
260260
",
261261
);
262+
}
263+
264+
#[test]
265+
fn goto_drop_temp_table() {
266+
assert_snapshot!(goto("
267+
create temp table t();
268+
drop table t$0;
269+
"), @r"
270+
╭▸
271+
2 │ create temp table t();
272+
│ ─ 2. destination
273+
3 │ drop table t;
274+
╰╴ ─ 1. source
275+
");
276+
}
277+
278+
#[test]
279+
fn goto_drop_temporary_table() {
280+
assert_snapshot!(goto("
281+
create temporary table t();
282+
drop table t$0;
283+
"), @r"
284+
╭▸
285+
2 │ create temporary table t();
286+
│ ─ 2. destination
287+
3 │ drop table t;
288+
╰╴ ─ 1. source
289+
");
290+
}
291+
292+
#[test]
293+
fn goto_drop_temp_table_with_pg_temp_schema() {
294+
assert_snapshot!(goto("
295+
create temp table t();
296+
drop table pg_temp.t$0;
297+
"), @r"
298+
╭▸
299+
2 │ create temp table t();
300+
│ ─ 2. destination
301+
3 │ drop table pg_temp.t;
302+
╰╴ ─ 1. source
303+
");
304+
}
262305

263-
// todo: temp tables
306+
#[test]
307+
fn goto_drop_temp_table_shadows_public() {
308+
// temp tables shadow public tables when no schema is specified
309+
assert_snapshot!(goto("
310+
create table t();
311+
create temp table t();
312+
drop table t$0;
313+
"), @r"
314+
╭▸
315+
3 │ create temp table t();
316+
│ ─ 2. destination
317+
4 │ drop table t;
318+
╰╴ ─ 1. source
319+
");
320+
}
321+
322+
#[test]
323+
fn goto_drop_public_table_when_temp_exists() {
324+
// can still access public table explicitly
325+
assert_snapshot!(goto("
326+
create table t();
327+
create temp table t();
328+
drop table public.t$0;
329+
"), @r"
330+
╭▸
331+
2 │ create table t();
332+
│ ─ 2. destination
333+
3 │ create temp table t();
334+
4 │ drop table public.t;
335+
╰╴ ─ 1. source
336+
");
264337
}
265338

266339
#[test]

crates/squawk_ide/src/resolve.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,30 @@ fn classify_name_ref_context(name_ref: &ast::NameRef) -> Option<NameRefContext>
3434
None
3535
}
3636

37-
fn resolve_table(binder: &Binder, table_name: &Name, schema: &Schema) -> Option<SyntaxNodePtr> {
38-
let symbol_id = binder.scopes[binder.root_scope()]
39-
.get(table_name)?
40-
.iter()
41-
.copied()
42-
.find(|id| {
37+
fn resolve_table(
38+
binder: &Binder,
39+
table_name: &Name,
40+
schema: &Option<Schema>,
41+
) -> Option<SyntaxNodePtr> {
42+
let symbols = binder.scopes[binder.root_scope()].get(table_name)?;
43+
44+
if let Some(schema) = schema {
45+
let symbol_id = symbols.iter().copied().find(|id| {
4346
let symbol = &binder.symbols[*id];
4447
symbol.kind == SymbolKind::Table && &symbol.schema == schema
4548
})?;
46-
Some(binder.symbols[symbol_id].ptr)
49+
return Some(binder.symbols[symbol_id].ptr);
50+
} else {
51+
for search_schema in [Schema::new("pg_temp"), Schema::new("public")] {
52+
if let Some(symbol_id) = symbols.iter().copied().find(|id| {
53+
let symbol = &binder.symbols[*id];
54+
symbol.kind == SymbolKind::Table && symbol.schema == search_schema
55+
}) {
56+
return Some(binder.symbols[symbol_id].ptr);
57+
}
58+
}
59+
}
60+
None
4761
}
4862

4963
fn find_containing_path(name_ref: &ast::NameRef) -> Option<ast::Path> {
@@ -61,15 +75,9 @@ fn extract_table_name(path: &ast::Path) -> Option<Name> {
6175
Some(Name::new(name_ref.syntax().text().to_string()))
6276
}
6377

64-
fn extract_schema_name(path: &ast::Path) -> Schema {
65-
let Some(qualifier) = path.qualifier() else {
66-
return Schema::Public;
67-
};
68-
let Some(segment) = qualifier.segment() else {
69-
return Schema::Public;
70-
};
71-
let Some(name_ref) = segment.name_ref() else {
72-
return Schema::Public;
73-
};
74-
Schema::from_name(Name::new(name_ref.syntax().text().to_string()))
78+
fn extract_schema_name(path: &ast::Path) -> Option<Schema> {
79+
path.qualifier()
80+
.and_then(|q| q.segment())
81+
.and_then(|s| s.name_ref())
82+
.map(|name_ref| Schema(Name::new(name_ref.syntax().text().to_string())))
7583
}

crates/squawk_ide/src/symbols.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,11 @@ use squawk_syntax::SyntaxNodePtr;
66
pub(crate) struct Name(pub(crate) SmolStr);
77

88
#[derive(Clone, Debug, PartialEq, Eq)]
9-
pub(crate) enum Schema {
10-
Public,
11-
Custom(Name),
12-
}
9+
pub(crate) struct Schema(pub(crate) Name);
1310

1411
impl Schema {
15-
pub(crate) fn from_name(name: Name) -> Self {
16-
if name == Name::new("public") {
17-
Schema::Public
18-
} else {
19-
Schema::Custom(name)
20-
}
12+
pub(crate) fn new(name: impl Into<SmolStr>) -> Self {
13+
Schema(Name::new(name))
2114
}
2215
}
2316

0 commit comments

Comments
 (0)