Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions crates/squawk_ide/src/ast_nav.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,37 @@ pub(crate) fn parent_source(node: &SyntaxNode) -> Option<ParentSouce> {
None
}

pub(crate) enum CreateTableArg {
Column(ast::Column),
Inherits(ast::Path),
LikeClause(ast::LikeClause),
TableConstraint(#[expect(unused)] ast::TableConstraint),
}

pub(crate) fn create_table_args(
create_table: &impl ast::HasCreateTable,
) -> impl Iterator<Item = CreateTableArg> {
let inherits_iter = create_table
.inherits()
.into_iter()
.flat_map(|inherits| inherits.paths())
.map(CreateTableArg::Inherits);

let args_iter = create_table
.table_arg_list()
.into_iter()
.flat_map(|arg_list| arg_list.args())
.map(|arg| match arg {
ast::TableArg::Column(column) => CreateTableArg::Column(column),
ast::TableArg::LikeClause(like_clause) => CreateTableArg::LikeClause(like_clause),
ast::TableArg::TableConstraint(constraint) => {
CreateTableArg::TableConstraint(constraint)
}
});

inherits_iter.chain(args_iter)
}

struct UnwrapParenExpr {
current: Option<ast::Expr>,
}
Expand Down
115 changes: 48 additions & 67 deletions crates/squawk_ide/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,48 +37,37 @@ fn columns_from_create_table_impl(
return;
}

if let Some(inherits) = create_table.inherits() {
for path in inherits.paths() {
if let Some((schema, table_name)) = name::schema_and_name_path(&path) {
let position = path.syntax().text_range().start();
if let Some(ResolvedTableName::Table(parent_table)) =
resolve_table_name(db, file, &table_name, &schema, position)
{
columns_from_create_table_impl(db, file, &parent_table, columns, depth + 1);
for arg in ast_nav::create_table_args(create_table) {
match arg {
ast_nav::CreateTableArg::Inherits(path) => {
if let Some((schema, table_name)) = name::schema_and_name_path(&path) {
let position = path.syntax().text_range().start();
if let Some(ResolvedTableName::Table(parent_table)) =
resolve_table_name(db, file, &table_name, &schema, position)
{
columns_from_create_table_impl(db, file, &parent_table, columns, depth + 1);
}
}
}
}
}

if let Some(arg_list) = create_table.table_arg_list() {
for arg in arg_list.args() {
match &arg {
ast::TableArg::Column(column) => {
if let Some(name) = column.name() {
let col_name = Name::from_node(&name);
columns.push((col_name, Some(SyntaxNodePtr::new(name.syntax()))));
}
ast_nav::CreateTableArg::Column(column) => {
if let Some(name) = column.name() {
let col_name = Name::from_node(&name);
columns.push((col_name, Some(SyntaxNodePtr::new(name.syntax()))));
}
ast::TableArg::LikeClause(like_clause) => {
if let Some(path) = like_clause.path()
&& let Some((schema, table_name)) = name::schema_and_name_path(&path)
}
ast_nav::CreateTableArg::LikeClause(like_clause) => {
if let Some(path) = like_clause.path()
&& let Some((schema, table_name)) = name::schema_and_name_path(&path)
{
let position = path.syntax().text_range().start();
if let Some(ResolvedTableName::Table(source_table)) =
resolve_table_name(db, file, &table_name, &schema, position)
{
let position = path.syntax().text_range().start();
if let Some(ResolvedTableName::Table(source_table)) =
resolve_table_name(db, file, &table_name, &schema, position)
{
columns_from_create_table_impl(
db,
file,
&source_table,
columns,
depth + 1,
);
}
columns_from_create_table_impl(db, file, &source_table, columns, depth + 1);
}
}
ast::TableArg::TableConstraint(_) => (),
}
ast_nav::CreateTableArg::TableConstraint(_) => (),
}
}
}
Expand All @@ -105,45 +94,37 @@ fn table_columns_impl(

let mut columns = vec![];

if let Some(inherits) = create_table.inherits() {
for path in inherits.paths() {
if let Some((schema, table_name)) = name::schema_and_name_path(&path) {
let position = path.syntax().text_range().start();
if let Some(ResolvedTableName::Table(parent_table)) =
resolve_table_name(db, file, &table_name, &schema, position)
{
let inherited_columns = table_columns_impl(db, file, &parent_table, depth + 1);
columns.extend(inherited_columns);
for arg in ast_nav::create_table_args(create_table) {
match arg {
ast_nav::CreateTableArg::Inherits(path) => {
if let Some((schema, table_name)) = name::schema_and_name_path(&path) {
let position = path.syntax().text_range().start();
if let Some(ResolvedTableName::Table(parent_table)) =
resolve_table_name(db, file, &table_name, &schema, position)
{
columns.extend(table_columns_impl(db, file, &parent_table, depth + 1));
}
}
}
}
}

if let Some(arg_list) = create_table.table_arg_list() {
for arg in arg_list.args() {
match &arg {
ast::TableArg::Column(column) => {
if let Some(name) = column.name() {
let ty = column.ty().and_then(|ty| infer_type_from_ty(&ty));
columns.push((Name::from_node(&name), ty));
}
ast_nav::CreateTableArg::Column(column) => {
if let Some(name) = column.name() {
let ty = column.ty().and_then(|ty| infer_type_from_ty(&ty));
columns.push((Name::from_node(&name), ty));
}
ast::TableArg::LikeClause(like_clause) => {
if let Some(path) = like_clause.path()
&& let Some((schema, table_name)) = name::schema_and_name_path(&path)
}
ast_nav::CreateTableArg::LikeClause(like_clause) => {
if let Some(path) = like_clause.path()
&& let Some((schema, table_name)) = name::schema_and_name_path(&path)
{
let position = path.syntax().text_range().start();
if let Some(ResolvedTableName::Table(source_table)) =
resolve_table_name(db, file, &table_name, &schema, position)
{
let position = path.syntax().text_range().start();
if let Some(ResolvedTableName::Table(source_table)) =
resolve_table_name(db, file, &table_name, &schema, position)
{
let like_columns =
table_columns_impl(db, file, &source_table, depth + 1);
columns.extend(like_columns);
}
columns.extend(table_columns_impl(db, file, &source_table, depth + 1));
}
}
ast::TableArg::TableConstraint(_) => (),
}
ast_nav::CreateTableArg::TableConstraint(_) => (),
}
}

Expand Down
46 changes: 15 additions & 31 deletions crates/squawk_ide/src/document_symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,7 @@ fn create_table_symbol(
create_table: impl ast::HasCreateTable,
) -> Option<DocumentSymbol> {
let path = create_table.path()?;
let segment = path.segment()?;
let name_node = segment.name()?;
let name_node = path.segment()?.name()?;

let (schema, table_name) = resolve_table_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, table_name);
Expand All @@ -283,13 +282,11 @@ fn create_table_symbol(
let focus_range = name_node.syntax().text_range();

let mut children = vec![];
if let Some(table_arg_list) = create_table.table_arg_list() {
for arg in table_arg_list.args() {
if let ast::TableArg::Column(column) = arg
&& let Some(column_symbol) = create_column_symbol(column)
{
children.push(column_symbol);
}
for arg in create_table.table_arg_list()?.args() {
if let ast::TableArg::Column(column) = arg
&& let Some(column_symbol) = create_column_symbol(column)
{
children.push(column_symbol);
}
}

Expand All @@ -309,12 +306,7 @@ fn create_table_as_symbol(
create_table_as: ast::CreateTableAs,
) -> Option<DocumentSymbol> {
let path = create_table_as.path()?;
let segment = path.segment()?;
let name_node = if let Some(name) = segment.name() {
name.syntax().clone()
} else {
return None;
};
let name_node = path.segment()?.name()?.syntax().clone();

let (schema, table_name) = resolve_table_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, table_name);
Expand All @@ -340,8 +332,7 @@ fn create_view_symbol(
create_view: ast::CreateView,
) -> Option<DocumentSymbol> {
let path = create_view.path()?;
let segment = path.segment()?;
let name_node = segment.name()?;
let name_node = path.segment()?.name()?;

let (schema, view_name) = resolve_view_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, view_name);
Expand Down Expand Up @@ -391,8 +382,7 @@ fn create_materialized_view_symbol(
create_view: ast::CreateMaterializedView,
) -> Option<DocumentSymbol> {
let path = create_view.path()?;
let segment = path.segment()?;
let name_node = segment.name()?;
let name_node = path.segment()?.name()?;

let (schema, view_name) = resolve_view_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, view_name);
Expand All @@ -415,8 +405,7 @@ fn create_function_symbol(
create_function: ast::CreateFunction,
) -> Option<DocumentSymbol> {
let path = create_function.path()?;
let segment = path.segment()?;
let name_node = segment.name()?;
let name_node = path.segment()?.name()?;

let (schema, function_name) = resolve_function_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, function_name);
Expand All @@ -440,8 +429,7 @@ fn create_aggregate_symbol(
create_aggregate: ast::CreateAggregate,
) -> Option<DocumentSymbol> {
let path = create_aggregate.path()?;
let segment = path.segment()?;
let name_node = segment.name()?;
let name_node = path.segment()?.name()?;

let (schema, aggregate_name) = resolve_aggregate_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, aggregate_name);
Expand All @@ -465,8 +453,7 @@ fn create_procedure_symbol(
create_procedure: ast::CreateProcedure,
) -> Option<DocumentSymbol> {
let path = create_procedure.path()?;
let segment = path.segment()?;
let name_node = segment.name()?;
let name_node = path.segment()?.name()?;

let (schema, procedure_name) = resolve_procedure_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, procedure_name);
Expand Down Expand Up @@ -507,8 +494,7 @@ fn create_domain_symbol(
create_domain: ast::CreateDomain,
) -> Option<DocumentSymbol> {
let path = create_domain.path()?;
let segment = path.segment()?;
let name_node = segment.name()?;
let name_node = path.segment()?.name()?;

let (schema, domain_name) = resolve_type_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, domain_name);
Expand All @@ -532,8 +518,7 @@ fn create_sequence_symbol(
create_sequence: ast::CreateSequence,
) -> Option<DocumentSymbol> {
let path = create_sequence.path()?;
let segment = path.segment()?;
let name_node = segment.name()?;
let name_node = path.segment()?.name()?;

let (schema, sequence_name) = resolve_sequence_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, sequence_name);
Expand Down Expand Up @@ -716,8 +701,7 @@ fn create_type_symbol(
create_type: ast::CreateType,
) -> Option<DocumentSymbol> {
let path = create_type.path()?;
let segment = path.segment()?;
let name_node = segment.name()?;
let name_node = path.segment()?.name()?;

let (schema, type_name) = resolve_type_info(db, file, &path)?;
let name = format!("{}.{}", schema.0, type_name);
Expand Down
12 changes: 12 additions & 0 deletions crates/squawk_ide/src/goto_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6177,6 +6177,18 @@ select COLUMN1$0, COLUMN2 from t;
");
}

#[test]
fn goto_cte_values_with_explicit_column_list_column1_not_found() {
goto_not_found(
"
with t(a, b) as (
values (1, 2), (3, 4)
)
select column1$0 from t;
",
);
}

#[test]
fn goto_qualified_column_with_schema_in_from_table() {
assert_snapshot!(goto("
Expand Down
Loading
Loading