Skip to content

Commit a6c6fcf

Browse files
authored
ide: create table as (#893)
1 parent 23085e7 commit a6c6fcf

File tree

5 files changed

+293
-140
lines changed

5 files changed

+293
-140
lines changed

crates/squawk_ide/src/binder.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ fn bind_file(b: &mut Binder, file: &ast::SourceFile) {
249249
fn bind_stmt(b: &mut Binder, stmt: ast::Stmt) {
250250
match stmt {
251251
ast::Stmt::CreateTable(create_table) => bind_create_table(b, create_table),
252+
ast::Stmt::CreateTableAs(create_table_as) => bind_create_table_as(b, create_table_as),
252253
ast::Stmt::CreateForeignTable(create_foreign_table) => {
253254
bind_create_table(b, create_foreign_table)
254255
}
@@ -318,6 +319,41 @@ fn bind_create_table(b: &mut Binder, create_table: impl ast::HasCreateTable) {
318319
b.scopes[root].insert(table_name, type_id);
319320
}
320321

322+
fn bind_create_table_as(b: &mut Binder, create_table_as: ast::CreateTableAs) {
323+
let Some(path) = create_table_as.path() else {
324+
return;
325+
};
326+
let Some(table_name) = item_name(&path) else {
327+
return;
328+
};
329+
let name_ptr = path_to_ptr(&path);
330+
let is_temp =
331+
create_table_as.temp_token().is_some() || create_table_as.temporary_token().is_some();
332+
let Some(schema) = schema_name(b, &path, is_temp) else {
333+
return;
334+
};
335+
336+
let table_id = b.symbols.alloc(Symbol {
337+
kind: SymbolKind::Table,
338+
ptr: name_ptr,
339+
schema: Some(schema.clone()),
340+
params: None,
341+
table: None,
342+
});
343+
344+
let type_id = b.symbols.alloc(Symbol {
345+
kind: SymbolKind::Type,
346+
ptr: name_ptr,
347+
schema: Some(schema),
348+
params: None,
349+
table: None,
350+
});
351+
352+
let root = b.root_scope();
353+
b.scopes[root].insert(table_name.clone(), table_id);
354+
b.scopes[root].insert(table_name, type_id);
355+
}
356+
321357
fn bind_create_index(b: &mut Binder, create_index: ast::CreateIndex) {
322358
let Some(name) = create_index.name() else {
323359
return;

crates/squawk_ide/src/document_symbols.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ pub fn document_symbols(file: &ast::SourceFile) -> Vec<DocumentSymbol> {
6565
symbols.push(symbol);
6666
}
6767
}
68+
ast::Stmt::CreateTableAs(create_table_as) => {
69+
if let Some(symbol) = create_table_as_symbol(&binder, create_table_as) {
70+
symbols.push(symbol);
71+
}
72+
}
6873
ast::Stmt::CreateForeignTable(create_foreign_table) => {
6974
if let Some(symbol) = create_table_symbol(&binder, create_foreign_table) {
7075
symbols.push(symbol);
@@ -289,6 +294,36 @@ fn create_table_symbol(
289294
})
290295
}
291296

297+
fn create_table_as_symbol(
298+
binder: &binder::Binder,
299+
create_table_as: ast::CreateTableAs,
300+
) -> Option<DocumentSymbol> {
301+
let path = create_table_as.path()?;
302+
let segment = path.segment()?;
303+
let name_node = if let Some(name) = segment.name() {
304+
name.syntax().clone()
305+
} else {
306+
return None;
307+
};
308+
309+
let (schema, table_name) = resolve_table_info(binder, &path)?;
310+
let name = format!("{}.{}", schema.0, table_name);
311+
312+
let full_range = create_table_as.syntax().text_range();
313+
let focus_range = name_node.text_range();
314+
315+
Some(DocumentSymbol {
316+
name,
317+
detail: None,
318+
kind: DocumentSymbolKind::Table,
319+
full_range,
320+
focus_range,
321+
// TODO: infer the column names, we need the same for views without
322+
// explicit column lists
323+
children: vec![],
324+
})
325+
}
326+
292327
fn create_view_symbol(
293328
binder: &binder::Binder,
294329
create_view: ast::CreateView,
@@ -959,6 +994,21 @@ create table users (
959994
");
960995
}
961996

997+
#[test]
998+
fn create_table_as() {
999+
assert_snapshot!(symbols("
1000+
create table t as select 1 a;
1001+
"), @r"
1002+
info: table: public.t
1003+
╭▸
1004+
2 │ create table t as select 1 a;
1005+
│ ┬────────────┯──────────────
1006+
│ │ │
1007+
│ │ focus range
1008+
╰╴full range
1009+
");
1010+
}
1011+
9621012
#[test]
9631013
fn create_schema() {
9641014
assert_snapshot!(symbols("

crates/squawk_ide/src/goto_definition.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,34 @@ select v.a$0 from v;
22472247
");
22482248
}
22492249

2250+
#[test]
2251+
fn goto_create_table_as_column() {
2252+
assert_snapshot!(goto("
2253+
create table t as select 1 a;
2254+
select a$0 from t;
2255+
"), @r"
2256+
╭▸
2257+
2 │ create table t as select 1 a;
2258+
│ ─ 2. destination
2259+
3 │ select a from t;
2260+
╰╴ ─ 1. source
2261+
");
2262+
}
2263+
2264+
#[test]
2265+
fn goto_select_from_create_table_as() {
2266+
assert_snapshot!(goto("
2267+
create table t as select 1 a;
2268+
select a from t$0;
2269+
"), @r"
2270+
╭▸
2271+
2 │ create table t as select 1 a;
2272+
│ ─ 2. destination
2273+
3 │ select a from t;
2274+
╰╴ ─ 1. source
2275+
");
2276+
}
2277+
22502278
#[test]
22512279
fn goto_view_with_explicit_column_list() {
22522280
assert_snapshot!(goto("

crates/squawk_ide/src/hover.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,21 @@ fn format_hover_for_column_node(
385385
{
386386
return format_view_column(&create_view, column_name, binder);
387387
}
388+
389+
if let Some(create_table_as) = ast::CreateTableAs::cast(a.clone()) {
390+
let column_name = if let Some(name) = ast::Name::cast(column_name_node.clone()) {
391+
Name::from_node(&name)
392+
} else {
393+
continue;
394+
};
395+
let path = create_table_as.path()?;
396+
let (schema, table_name) = resolve::resolve_table_info(binder, &path)?;
397+
return Some(ColumnHover::schema_table_column(
398+
&schema.to_string(),
399+
&table_name,
400+
&column_name.to_string(),
401+
));
402+
}
388403
}
389404

390405
let column = column_name_node.ancestors().find_map(ast::Column::cast)?;
@@ -3614,6 +3629,19 @@ select a$0, b from v;
36143629
");
36153630
}
36163631

3632+
#[test]
3633+
fn hover_on_select_column_from_create_table_as() {
3634+
assert_snapshot!(check_hover("
3635+
create table t as select 1 a;
3636+
select a$0 from t;
3637+
"), @r"
3638+
hover: column public.t.a
3639+
╭▸
3640+
3 │ select a from t;
3641+
╰╴ ─ hover
3642+
");
3643+
}
3644+
36173645
#[test]
36183646
fn hover_on_select_from_view_with_schema() {
36193647
assert_snapshot!(check_hover("

0 commit comments

Comments
 (0)