agent_patch
runs/2026-02-28__18-27-22__gpt-5-4/flux-pr-1435/flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/agent-logs/agent.patch
130361 bytes
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/mod.rs b/app/src/ast/mod.rs
index 9185c9d..cd08b7d 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/ast/mod.rs
+++ b/app/src/ast/mod.rs
@@ -25,6 +25,8 @@ use alloc::{
};
use core::fmt::{self, Display};
+use core::hash;
+use core::cmp::Ordering;
use core::ops::Deref;
#[cfg(feature = "serde")]
@@ -73,6 +75,8 @@ pub use self::value::{
escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
TrimWhereField, Value,
};
+pub use self::spans::Spanned;
+pub use crate::tokenizer::Span;
use crate::ast::helpers::stmt_data_loading::{
DataLoadingOptions, StageLoadSelectItem, StageParamsObject,
@@ -87,6 +91,7 @@ mod dml;
pub mod helpers;
mod operator;
mod query;
+mod spans;
mod trigger;
mod value;
@@ -131,7 +136,7 @@ where
}
/// An identifier, decomposed into its value or character data and the quote style.
-#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct Ident {
@@ -140,6 +145,37 @@ pub struct Ident {
/// The starting quote if any. Valid quote characters are the single quote,
/// double quote, backtick, and opening square bracket.
pub quote_style: Option<char>,
+ /// The span of the identifier in the original SQL string.
+ pub span: Span,
+}
+
+impl PartialEq for Ident {
+ fn eq(&self, other: &Self) -> bool {
+ self.value == other.value && self.quote_style == other.quote_style
+ }
+}
+
+impl Eq for Ident {}
+
+impl PartialOrd for Ident {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for Ident {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.value
+ .cmp(&other.value)
+ .then_with(|| self.quote_style.cmp(&other.quote_style))
+ }
+}
+
+impl hash::Hash for Ident {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.value.hash(state);
+ self.quote_style.hash(state);
+ }
}
impl Ident {
@@ -151,6 +187,7 @@ impl Ident {
Ident {
value: value.into(),
quote_style: None,
+ span: Span::empty(),
}
}
@@ -164,6 +201,32 @@ impl Ident {
Ident {
value: value.into(),
quote_style: Some(quote),
+ span: Span::empty(),
+ }
+ }
+
+ /// Create a new identifier with an explicit span.
+ pub fn with_span<S>(span: Span, value: S) -> Self
+ where
+ S: Into<String>,
+ {
+ Ident {
+ value: value.into(),
+ quote_style: None,
+ span,
+ }
+ }
+
+ /// Create a quoted identifier with an explicit span.
+ pub fn with_quote_and_span<S>(quote: char, span: Span, value: S) -> Self
+ where
+ S: Into<String>,
+ {
+ assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
+ Ident {
+ value: value.into(),
+ quote_style: Some(quote),
+ span,
}
}
}
@@ -173,6 +236,7 @@ impl From<&str> for Ident {
Ident {
value: value.to_string(),
quote_style: None,
+ span: Span::empty(),
}
}
}
diff --git a/app/src/ast/spans.rs b/app/src/ast/spans.rs
new file mode 100644
index 0000000..286a233
--- /dev/null
+++ b/app/src/ast/spans.rs
@@ -0,0 +1,664 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::ast::{
+ AlterIndexOperation, AlterPolicyOperation, Array, Assignment, AssignmentTarget, Cte,
+ ColumnDef, Expr, Fetch, FromTable, Function, FunctionArg, FunctionArgExpr, FunctionArguments,
+ GroupByExpr, HiveSetLocation, Ident, Join, JoinConstraint, JoinOperator,
+ NamedWindowDefinition, ObjectName, Offset, OrderBy, OrderByExpr, Query, SchemaName, Select,
+ SelectInto, SelectItem, SetExpr, SqlOption, Statement, TableAlias, TableFactor,
+ TableFunctionArgs, TableWithJoins, Top, TopQuantity, Use, Value, Values, With,
+};
+use crate::tokenizer::{Span, TokenWithLocation};
+
+fn union_spans<I: IntoIterator<Item = Span>>(iter: I) -> Span {
+ Span::union_iter(iter)
+}
+
+pub trait Spanned {
+ fn span(&self) -> Span;
+}
+
+impl<T: Spanned> Spanned for Box<T> {
+ fn span(&self) -> Span {
+ self.as_ref().span()
+ }
+}
+
+impl<T: Spanned> Spanned for Option<T> {
+ fn span(&self) -> Span {
+ self.as_ref().map_or_else(Span::empty, Spanned::span)
+ }
+}
+
+impl<T: Spanned> Spanned for Vec<T> {
+ fn span(&self) -> Span {
+ union_spans(self.iter().map(Spanned::span))
+ }
+}
+
+impl Spanned for TokenWithLocation {
+ fn span(&self) -> Span {
+ self.span
+ }
+}
+
+impl Spanned for Ident {
+ fn span(&self) -> Span {
+ self.span
+ }
+}
+
+impl Spanned for ObjectName {
+ fn span(&self) -> Span {
+ self.0.span()
+ }
+}
+
+impl Spanned for Value {
+ fn span(&self) -> Span {
+ Span::empty()
+ }
+}
+
+impl Spanned for Query {
+ fn span(&self) -> Span {
+ union_spans([
+ self.with.span(),
+ self.body.span(),
+ self.order_by.span(),
+ self.limit.span(),
+ self.limit_by.span(),
+ self.offset.span(),
+ self.fetch.span(),
+ ])
+ }
+}
+
+impl Spanned for With {
+ fn span(&self) -> Span {
+ self.cte_tables.span()
+ }
+}
+
+impl Spanned for Cte {
+ fn span(&self) -> Span {
+ union_spans([self.alias.span(), self.query.span(), self.from.span()])
+ }
+}
+
+impl Spanned for SetExpr {
+ fn span(&self) -> Span {
+ match self {
+ SetExpr::Select(select) => select.span(),
+ SetExpr::Query(query) => query.span(),
+ SetExpr::SetOperation { left, right, .. } => left.span().union(&right.span()),
+ SetExpr::Values(values) => values.span(),
+ SetExpr::Insert(statement) | SetExpr::Update(statement) => statement.span(),
+ SetExpr::Table(_) => Span::empty(),
+ }
+ }
+}
+
+impl Spanned for Select {
+ fn span(&self) -> Span {
+ union_spans([
+ self.projection.span(),
+ self.into.span(),
+ self.from.span(),
+ self.selection.span(),
+ self.group_by.span(),
+ self.having.span(),
+ self.cluster_by.span(),
+ self.distribute_by.span(),
+ self.sort_by.span(),
+ self.named_window.span(),
+ self.qualify.span(),
+ self.top.span(),
+ ])
+ }
+}
+
+impl Spanned for Values {
+ fn span(&self) -> Span {
+ union_spans(
+ self.rows
+ .iter()
+ .map(|row| union_spans(row.iter().map(Spanned::span))),
+ )
+ }
+}
+
+impl Spanned for OrderBy {
+ fn span(&self) -> Span {
+ self.exprs.span()
+ }
+}
+
+impl Spanned for OrderByExpr {
+ fn span(&self) -> Span {
+ self.expr.span()
+ }
+}
+
+impl Spanned for Offset {
+ fn span(&self) -> Span {
+ self.value.span()
+ }
+}
+
+impl Spanned for Fetch {
+ fn span(&self) -> Span {
+ self.quantity.span()
+ }
+}
+
+impl Spanned for TableWithJoins {
+ fn span(&self) -> Span {
+ self.relation.span().union(&self.joins.span())
+ }
+}
+
+impl Spanned for Join {
+ fn span(&self) -> Span {
+ self.relation
+ .span()
+ .union(&match &self.join_operator {
+ JoinOperator::Inner(constraint)
+ | JoinOperator::LeftOuter(constraint)
+ | JoinOperator::RightOuter(constraint)
+ | JoinOperator::FullOuter(constraint)
+ | JoinOperator::Semi(constraint)
+ | JoinOperator::LeftSemi(constraint)
+ | JoinOperator::RightSemi(constraint)
+ | JoinOperator::Anti(constraint)
+ | JoinOperator::LeftAnti(constraint)
+ | JoinOperator::RightAnti(constraint) => constraint.span(),
+ JoinOperator::AsOf {
+ match_condition,
+ constraint,
+ } => match_condition.span().union(&constraint.span()),
+ JoinOperator::CrossJoin
+ | JoinOperator::CrossApply
+ | JoinOperator::OuterApply => Span::empty(),
+ })
+ }
+}
+
+impl Spanned for JoinConstraint {
+ fn span(&self) -> Span {
+ match self {
+ JoinConstraint::On(expr) => expr.span(),
+ JoinConstraint::Using(attrs) => attrs.span(),
+ JoinConstraint::Natural | JoinConstraint::None => Span::empty(),
+ }
+ }
+}
+
+impl Spanned for TableFactor {
+ fn span(&self) -> Span {
+ match self {
+ TableFactor::Table { name, alias, args, .. } => {
+ union_spans([name.span(), alias.span(), args.span()])
+ }
+ TableFactor::Derived {
+ subquery, alias, ..
+ } => subquery.span().union(&alias.span()),
+ TableFactor::TableFunction { expr, alias } => expr.span().union(&alias.span()),
+ TableFactor::Function {
+ name, args, alias, ..
+ } => union_spans([name.span(), args.span(), alias.span()]),
+ TableFactor::UNNEST {
+ array_exprs, alias, ..
+ } => array_exprs.span().union(&alias.span()),
+ TableFactor::NestedJoin {
+ table_with_joins,
+ alias,
+ } => table_with_joins.span().union(&alias.span()),
+ _ => Span::empty(),
+ }
+ }
+}
+
+impl Spanned for TableAlias {
+ fn span(&self) -> Span {
+ self.name.span().union(&self.columns.span())
+ }
+}
+
+impl Spanned for SelectItem {
+ fn span(&self) -> Span {
+ match self {
+ SelectItem::UnnamedExpr(expr) => expr.span(),
+ SelectItem::ExprWithAlias { expr, alias } => expr.span().union(&alias.span()),
+ SelectItem::QualifiedWildcard(name, _) => name.span(),
+ SelectItem::Wildcard(_) => Span::empty(),
+ }
+ }
+}
+
+impl Spanned for Function {
+ fn span(&self) -> Span {
+ union_spans([
+ self.name.span(),
+ self.parameters.span(),
+ self.args.span(),
+ self.filter.span(),
+ self.within_group.span(),
+ ])
+ }
+}
+
+impl Spanned for FunctionArguments {
+ fn span(&self) -> Span {
+ match self {
+ FunctionArguments::None => Span::empty(),
+ FunctionArguments::Subquery(query) => query.span(),
+ FunctionArguments::List(list) => list.args.span(),
+ }
+ }
+}
+
+impl Spanned for TableFunctionArgs {
+ fn span(&self) -> Span {
+ self.args.span()
+ }
+}
+
+impl Spanned for SelectInto {
+ fn span(&self) -> Span {
+ self.name.span()
+ }
+}
+
+impl Spanned for Top {
+ fn span(&self) -> Span {
+ self.quantity.span()
+ }
+}
+
+impl Spanned for TopQuantity {
+ fn span(&self) -> Span {
+ match self {
+ TopQuantity::Expr(expr) => expr.span(),
+ TopQuantity::Constant(_) => Span::empty(),
+ }
+ }
+}
+
+impl Spanned for NamedWindowDefinition {
+ fn span(&self) -> Span {
+ self.0.span()
+ }
+}
+
+impl Spanned for FunctionArg {
+ fn span(&self) -> Span {
+ match self {
+ FunctionArg::Named { name, arg, .. } => name.span().union(&arg.span()),
+ FunctionArg::ExprNamed { name, arg, .. } => name.span().union(&arg.span()),
+ FunctionArg::Unnamed(arg) => arg.span(),
+ }
+ }
+}
+
+impl Spanned for FunctionArgExpr {
+ fn span(&self) -> Span {
+ match self {
+ FunctionArgExpr::Expr(expr) => expr.span(),
+ FunctionArgExpr::QualifiedWildcard(name) => name.span(),
+ FunctionArgExpr::Wildcard => Span::empty(),
+ }
+ }
+}
+
+impl Spanned for GroupByExpr {
+ fn span(&self) -> Span {
+ match self {
+ GroupByExpr::All(_) => Span::empty(),
+ GroupByExpr::Expressions(exprs, _) => exprs.span(),
+ }
+ }
+}
+
+impl Spanned for Array {
+ fn span(&self) -> Span {
+ self.elem.span()
+ }
+}
+
+impl Spanned for AssignmentTarget {
+ fn span(&self) -> Span {
+ match self {
+ AssignmentTarget::ColumnName(name) => name.span(),
+ AssignmentTarget::Tuple(names) => names.span(),
+ }
+ }
+}
+
+impl Spanned for Assignment {
+ fn span(&self) -> Span {
+ self.target.span().union(&self.value.span())
+ }
+}
+
+impl Spanned for ColumnDef {
+ fn span(&self) -> Span {
+ self.name.span().union(&self.collation.span())
+ }
+}
+
+impl Spanned for crate::ast::MapAccessKey {
+ fn span(&self) -> Span {
+ self.key.span()
+ }
+}
+
+impl Spanned for SqlOption {
+ fn span(&self) -> Span {
+ match self {
+ SqlOption::Clustered(_) => Span::empty(),
+ SqlOption::Ident(ident) => ident.span(),
+ SqlOption::KeyValue { key, value } => key.span().union(&value.span()),
+ SqlOption::Partition {
+ column_name,
+ for_values,
+ ..
+ } => column_name.span().union(&for_values.span()),
+ }
+ }
+}
+
+impl Spanned for FromTable {
+ fn span(&self) -> Span {
+ match self {
+ FromTable::WithFromKeyword(items) | FromTable::WithoutKeyword(items) => items.span(),
+ }
+ }
+}
+
+impl Spanned for HiveSetLocation {
+ fn span(&self) -> Span {
+ self.location.span()
+ }
+}
+
+impl Spanned for AlterIndexOperation {
+ fn span(&self) -> Span {
+ match self {
+ AlterIndexOperation::RenameIndex { index_name } => index_name.span(),
+ }
+ }
+}
+
+impl Spanned for AlterPolicyOperation {
+ fn span(&self) -> Span {
+ match self {
+ AlterPolicyOperation::Rename { new_name } => new_name.span(),
+ AlterPolicyOperation::Apply {
+ using, with_check, ..
+ } => using.span().union(&with_check.span()),
+ }
+ }
+}
+
+impl Spanned for Use {
+ fn span(&self) -> Span {
+ match self {
+ Use::Catalog(name)
+ | Use::Schema(name)
+ | Use::Database(name)
+ | Use::Warehouse(name)
+ | Use::Object(name) => name.span(),
+ Use::Default => Span::empty(),
+ }
+ }
+}
+
+impl Spanned for SchemaName {
+ fn span(&self) -> Span {
+ match self {
+ SchemaName::Simple(name) => name.span(),
+ SchemaName::UnnamedAuthorization(ident) => ident.span(),
+ SchemaName::NamedAuthorization(name, ident) => name.span().union(&ident.span()),
+ }
+ }
+}
+
+impl Spanned for Expr {
+ fn span(&self) -> Span {
+ match self {
+ Expr::Identifier(ident) => ident.span(),
+ Expr::CompoundIdentifier(idents) => idents.span(),
+ Expr::BinaryOp { left, right, .. } => left.span().union(&right.span()),
+ Expr::UnaryOp { expr, .. } => expr.span(),
+ Expr::Nested(expr) => expr.span(),
+ Expr::Value(value) => value.span(),
+ Expr::TypedString { .. } => Span::empty(),
+ Expr::MapAccess { column, keys } => column.span().union(&keys.span()),
+ Expr::Function(function) => function.span(),
+ Expr::Exists { subquery, .. } => subquery.span(),
+ Expr::Subquery(query) => query.span(),
+ Expr::Substring {
+ expr,
+ substring_from,
+ substring_for,
+ ..
+ } => union_spans([expr.span(), substring_from.span(), substring_for.span()]),
+ Expr::Trim {
+ expr,
+ trim_what,
+ trim_characters,
+ ..
+ } => union_spans([expr.span(), trim_what.span(), trim_characters.span()]),
+ Expr::Collate { expr, collation } => expr.span().union(&collation.span()),
+ Expr::InList { expr, list, .. } => expr.span().union(&list.span()),
+ Expr::InSubquery { expr, subquery, .. } => expr.span().union(&subquery.span()),
+ Expr::Between {
+ expr, low, high, ..
+ } => union_spans([expr.span(), low.span(), high.span()]),
+ Expr::Case {
+ operand,
+ conditions,
+ results,
+ else_result,
+ } => union_spans([
+ operand.span(),
+ conditions.span(),
+ results.span(),
+ else_result.span(),
+ ]),
+ Expr::Cast { expr, .. }
+ | Expr::AtTimeZone { timestamp: expr, .. }
+ | Expr::Extract { expr, .. }
+ | Expr::Ceil { expr, .. }
+ | Expr::Floor { expr, .. }
+ | Expr::Position { expr, .. }
+ | Expr::Overlay { expr, .. }
+ | Expr::OuterJoin(expr)
+ | Expr::Prior(expr) => expr.span(),
+ Expr::Array(array) => array.span(),
+ Expr::Interval(interval) => interval.value.span(),
+ Expr::Tuple(exprs) => exprs.span(),
+ Expr::GroupingSets(exprs) | Expr::Cube(exprs) | Expr::Rollup(exprs) => union_spans(
+ exprs.iter().map(|items| union_spans(items.iter().map(Spanned::span))),
+ ),
+ Expr::Struct { values, .. } => values.span(),
+ Expr::Named { expr, name } => expr.span().union(&name.span()),
+ Expr::Dictionary(fields) => union_spans(
+ fields
+ .iter()
+ .map(|field| field.key.span().union(&field.value.span())),
+ ),
+ Expr::Map(map) => union_spans(
+ map.entries
+ .iter()
+ .map(|entry| entry.key.span().union(&entry.value.span())),
+ ),
+ Expr::Subscript { expr, subscript } => expr.span().union(&subscript.span()),
+ Expr::IntroducedString { .. }
+ | Expr::MatchAgainst { .. }
+ | Expr::Wildcard
+ | Expr::QualifiedWildcard(_)
+ | Expr::Lambda(_) => Span::empty(),
+ _ => Span::empty(),
+ }
+ }
+}
+
+impl Spanned for crate::ast::Subscript {
+ fn span(&self) -> Span {
+ match self {
+ crate::ast::Subscript::Index { index } => index.span(),
+ crate::ast::Subscript::Slice {
+ lower_bound,
+ upper_bound,
+ stride,
+ } => union_spans([lower_bound.span(), upper_bound.span(), stride.span()]),
+ }
+ }
+}
+
+impl<T: Spanned> Spanned for crate::ast::OneOrManyWithParens<T> {
+ fn span(&self) -> Span {
+ union_spans(self.iter().map(Spanned::span))
+ }
+}
+
+impl Spanned for Statement {
+ fn span(&self) -> Span {
+ match self {
+ Statement::Query(query) => query.span(),
+ Statement::Insert(insert) => insert.table_name.span().union(&insert.source.span()),
+ Statement::Update {
+ table,
+ assignments,
+ from,
+ selection,
+ ..
+ } => union_spans([table.span(), assignments.span(), from.span(), selection.span()]),
+ Statement::Delete(delete) => {
+ union_spans([delete.from.span(), delete.using.span(), delete.selection.span()])
+ }
+ Statement::CreateView { name, query, .. } => name.span().union(&query.span()),
+ Statement::CreateTable(create) => create.name.span().union(&create.columns.span()),
+ Statement::Drop { names, .. } => names.span(),
+ Statement::AlterTable {
+ name,
+ location,
+ on_cluster,
+ ..
+ } => union_spans([name.span(), location.span(), on_cluster.span()]),
+ Statement::AlterIndex { name, operation } => name.span().union(&operation.span()),
+ Statement::AlterView {
+ name,
+ columns,
+ query,
+ with_options,
+ } => union_spans([name.span(), columns.span(), query.span(), with_options.span()]),
+ Statement::CreateSchema { schema_name, .. } => schema_name.span(),
+ Statement::CreateDatabase { db_name, .. } => db_name.span(),
+ Statement::CreateFunction { name, .. } => name.span(),
+ Statement::CreateRole { names, .. } => names.span(),
+ Statement::CreateSecret {
+ name,
+ storage_specifier,
+ secret_type,
+ ..
+ } => union_spans([name.span(), storage_specifier.span(), secret_type.span()]),
+ Statement::CreatePolicy {
+ name,
+ table_name,
+ using,
+ with_check,
+ ..
+ } => union_spans([name.span(), table_name.span(), using.span(), with_check.span()]),
+ Statement::AlterRole { name, .. } => name.span(),
+ Statement::AlterPolicy {
+ name,
+ table_name,
+ operation,
+ } => union_spans([name.span(), table_name.span(), operation.span()]),
+ Statement::AttachDatabase {
+ schema_name,
+ database_file_name,
+ ..
+ } => schema_name.span().union(&database_file_name.span()),
+ Statement::AttachDuckDBDatabase {
+ database_path,
+ database_alias,
+ ..
+ } => union_spans([database_path.span(), database_alias.span()]),
+ Statement::DetachDuckDBDatabase { database_alias, .. } => database_alias.span(),
+ Statement::DropSecret {
+ name,
+ storage_specifier,
+ ..
+ } => name.span().union(&storage_specifier.span()),
+ Statement::DropPolicy {
+ name, table_name, ..
+ } => name.span().union(&table_name.span()),
+ Statement::Fetch { name, into, .. } => name.span().union(&into.span()),
+ Statement::Flush { tables, .. } => tables.span(),
+ Statement::SetRole { role_name, .. } => role_name.span(),
+ Statement::SetVariable {
+ variables, value, ..
+ } => variables.span().union(&value.span()),
+ Statement::SetTimeZone { value, .. } => value.span(),
+ Statement::ShowVariable { variable } => variable.span(),
+ Statement::ShowCreate { obj_name, .. } => obj_name.span(),
+ Statement::Use(use_stmt) => use_stmt.span(),
+ Statement::Rollback { savepoint, .. } => savepoint.span(),
+ Statement::Comment { object_name, .. } => object_name.span(),
+ Statement::CreateTrigger {
+ name,
+ table_name,
+ referenced_table_name,
+ condition,
+ ..
+ } => union_spans([
+ name.span(),
+ table_name.span(),
+ referenced_table_name.span(),
+ condition.span(),
+ ]),
+ Statement::DropTrigger {
+ trigger_name,
+ table_name,
+ ..
+ } => trigger_name.span().union(&table_name.span()),
+ Statement::CreateProcedure { name, body, .. } => name.span().union(&body.span()),
+ Statement::CreateMacro { name, .. } => name.span(),
+ Statement::CreateStage { name, .. } => name.span(),
+ Statement::Assert {
+ condition, message, ..
+ } => condition.span().union(&message.span()),
+ Statement::Grant {
+ grantees,
+ granted_by,
+ ..
+ } => grantees.span().union(&granted_by.span()),
+ Statement::Revoke {
+ grantees,
+ granted_by,
+ ..
+ } => grantees.span().union(&granted_by.span()),
+ Statement::Deallocate { name, .. } => name.span(),
+ _ => Span::empty(),
+ }
+ }
+}
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/parser/mod.rs b/app/src/parser/mod.rs
index 6767f35..76da619 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -372,6 +372,7 @@ impl<'a> Parser<'a> {
.map(|token| TokenWithLocation {
token,
location: Location { line: 0, column: 0 },
+ span: crate::tokenizer::Span::empty(),
})
.collect();
self.with_tokens_with_locations(tokens_with_locations)
@@ -914,18 +915,20 @@ impl<'a> Parser<'a> {
t @ (Token::Word(_) | Token::SingleQuotedString(_)) => {
if self.peek_token().token == Token::Period {
let mut id_parts: Vec<Ident> = vec![match t {
- Token::Word(w) => w.to_ident(),
- Token::SingleQuotedString(s) => Ident::with_quote('\'', s),
+ Token::Word(w) => w.to_ident_with_span(next_token.span),
+ Token::SingleQuotedString(s) => {
+ Ident::with_quote_and_span('\'', next_token.span, s)
+ }
_ => unreachable!(), // We matched above
}];
while self.consume_token(&Token::Period) {
let next_token = self.next_token();
match next_token.token {
- Token::Word(w) => id_parts.push(w.to_ident()),
+ Token::Word(w) => id_parts.push(w.to_ident_with_span(next_token.span)),
Token::SingleQuotedString(s) => {
// SQLite has single-quoted identifiers
- id_parts.push(Ident::with_quote('\'', s))
+ id_parts.push(Ident::with_quote_and_span('\'', next_token.span, s))
}
Token::Mul => {
return Ok(Expr::QualifiedWildcard(ObjectName(id_parts)));
@@ -1030,6 +1033,7 @@ impl<'a> Parser<'a> {
fn parse_expr_prefix_by_reserved_word(
&mut self,
w: &Word,
+ span: crate::tokenizer::Span,
) -> Result<Option<Expr>, ParserError> {
match w.keyword {
Keyword::TRUE | Keyword::FALSE if self.dialect.supports_boolean_literals() => {
@@ -1047,7 +1051,7 @@ impl<'a> Parser<'a> {
if dialect_of!(self is PostgreSqlDialect | GenericDialect) =>
{
Ok(Some(Expr::Function(Function {
- name: ObjectName(vec![w.to_ident()]),
+ name: ObjectName(vec![w.to_ident_with_span(span)]),
parameters: FunctionArguments::None,
args: FunctionArguments::None,
null_treatment: None,
@@ -1061,7 +1065,7 @@ impl<'a> Parser<'a> {
| Keyword::CURRENT_DATE
| Keyword::LOCALTIME
| Keyword::LOCALTIMESTAMP => {
- Ok(Some(self.parse_time_functions(ObjectName(vec![w.to_ident()]))?))
+ Ok(Some(self.parse_time_functions(ObjectName(vec![w.to_ident_with_span(span)]))?))
}
Keyword::CASE => Ok(Some(self.parse_case_expr()?)),
Keyword::CONVERT => Ok(Some(self.parse_convert_expr(false)?)),
@@ -1086,7 +1090,7 @@ impl<'a> Parser<'a> {
Keyword::CEIL => Ok(Some(self.parse_ceil_floor_expr(true)?)),
Keyword::FLOOR => Ok(Some(self.parse_ceil_floor_expr(false)?)),
Keyword::POSITION if self.peek_token().token == Token::LParen => {
- Ok(Some(self.parse_position_expr(w.to_ident())?))
+ Ok(Some(self.parse_position_expr(w.to_ident_with_span(span))?))
}
Keyword::SUBSTRING => Ok(Some(self.parse_substring_expr()?)),
Keyword::OVERLAY => Ok(Some(self.parse_overlay_expr()?)),
@@ -1105,7 +1109,7 @@ impl<'a> Parser<'a> {
let query = self.parse_query()?;
self.expect_token(&Token::RParen)?;
Ok(Some(Expr::Function(Function {
- name: ObjectName(vec![w.to_ident()]),
+ name: ObjectName(vec![w.to_ident_with_span(span)]),
parameters: FunctionArguments::None,
args: FunctionArguments::Subquery(query),
filter: None,
@@ -1134,15 +1138,19 @@ impl<'a> Parser<'a> {
}
// Tries to parse an expression by a word that is not known to have a special meaning in the dialect.
- fn parse_expr_prefix_by_unreserved_word(&mut self, w: &Word) -> Result<Expr, ParserError> {
+ fn parse_expr_prefix_by_unreserved_word(
+ &mut self,
+ w: &Word,
+ span: crate::tokenizer::Span,
+ ) -> Result<Expr, ParserError> {
match self.peek_token().token {
Token::LParen | Token::Period => {
- let mut id_parts: Vec<Ident> = vec![w.to_ident()];
+ let mut id_parts: Vec<Ident> = vec![w.to_ident_with_span(span)];
let mut ends_with_wildcard = false;
while self.consume_token(&Token::Period) {
let next_token = self.next_token();
match next_token.token {
- Token::Word(w) => id_parts.push(w.to_ident()),
+ Token::Word(w) => id_parts.push(w.to_ident_with_span(next_token.span)),
Token::Mul => {
// Postgres explicitly allows funcnm(tablenm.*) and the
// function array_agg traverses this control flow
@@ -1153,7 +1161,9 @@ impl<'a> Parser<'a> {
return self.expected("an identifier after '.'", next_token);
}
}
- Token::SingleQuotedString(s) => id_parts.push(Ident::with_quote('\'', s)),
+ Token::SingleQuotedString(s) => {
+ id_parts.push(Ident::with_quote_and_span('\'', next_token.span, s))
+ }
_ => {
return self.expected("an identifier or a '*' after '.'", next_token);
}
@@ -1194,11 +1204,11 @@ impl<'a> Parser<'a> {
Token::Arrow if self.dialect.supports_lambda_functions() => {
self.expect_token(&Token::Arrow)?;
Ok(Expr::Lambda(LambdaFunction {
- params: OneOrManyWithParens::One(w.to_ident()),
+ params: OneOrManyWithParens::One(w.to_ident_with_span(span)),
body: Box::new(self.parse_expr()?),
}))
}
- _ => Ok(Expr::Identifier(w.to_ident())),
+ _ => Ok(Expr::Identifier(w.to_ident_with_span(span))),
}
}
@@ -1251,6 +1261,7 @@ impl<'a> Parser<'a> {
let next_token = self.next_token();
let expr = match next_token.token {
Token::Word(w) => {
+ let span = next_token.span;
// The word we consumed may fall into one of two cases: it has a special meaning, or not.
// For example, in Snowflake, the word `interval` may have two meanings depending on the context:
// `SELECT CURRENT_DATE() + INTERVAL '1 DAY', MAX(interval) FROM tbl;`
@@ -1259,12 +1270,12 @@ impl<'a> Parser<'a> {
//
// We first try to parse the word and following tokens as a special expression, and if that fails,
// we rollback and try to parse it as an identifier.
- match self.try_parse(|parser| parser.parse_expr_prefix_by_reserved_word(&w)) {
+ match self.try_parse(|parser| parser.parse_expr_prefix_by_reserved_word(&w, span)) {
// This word indicated an expression prefix and parsing was successful
Ok(Some(expr)) => Ok(expr),
// No expression prefix associated with this word
- Ok(None) => Ok(self.parse_expr_prefix_by_unreserved_word(&w)?),
+ Ok(None) => Ok(self.parse_expr_prefix_by_unreserved_word(&w, span)?),
// If parsing of the word as a special expression failed, we are facing two options:
// 1. The statement is malformed, e.g. `SELECT INTERVAL '1 DAI` (`DAI` instead of `DAY`)
@@ -1275,7 +1286,7 @@ impl<'a> Parser<'a> {
Err(e) => {
if !self.dialect.is_reserved_for_identifier(w.keyword) {
if let Ok(Some(expr)) = self.maybe_parse(|parser| {
- parser.parse_expr_prefix_by_unreserved_word(&w)
+ parser.parse_expr_prefix_by_unreserved_word(&w, span)
}) {
return Ok(expr);
}
@@ -1377,7 +1388,7 @@ impl<'a> Parser<'a> {
} else {
let tok = self.next_token();
let key = match tok.token {
- Token::Word(word) => word.to_ident(),
+ Token::Word(word) => word.to_ident_with_span(tok.span),
_ => {
return parser_err!(
format!("Expected identifier, found: {tok}"),
@@ -1471,7 +1482,7 @@ impl<'a> Parser<'a> {
while p.consume_token(&Token::Period) {
let tok = p.next_token();
let name = match tok.token {
- Token::Word(word) => word.to_ident(),
+ Token::Word(word) => word.to_ident_with_span(tok.span),
_ => return p.expected("identifier", tok),
};
let func = match p.parse_function(ObjectName(vec![name]))? {
@@ -3299,6 +3310,7 @@ impl<'a> Parser<'a> {
if let Some(TokenWithLocation {
token: Token::Whitespace(_),
location: _,
+ span: _,
}) = token
{
continue;
@@ -3306,6 +3318,7 @@ impl<'a> Parser<'a> {
break token.cloned().unwrap_or(TokenWithLocation {
token: Token::EOF,
location: Location { line: 0, column: 0 },
+ span: crate::tokenizer::Span::empty(),
});
})
}
@@ -3319,12 +3332,14 @@ impl<'a> Parser<'a> {
Some(TokenWithLocation {
token: Token::Whitespace(_),
location: _,
+ span: _,
}) => continue,
non_whitespace => {
if n == 0 {
return non_whitespace.cloned().unwrap_or(TokenWithLocation {
token: Token::EOF,
location: Location { line: 0, column: 0 },
+ span: crate::tokenizer::Span::empty(),
});
}
n -= 1;
@@ -3347,6 +3362,7 @@ impl<'a> Parser<'a> {
.unwrap_or(TokenWithLocation {
token: Token::EOF,
location: Location { line: 0, column: 0 },
+ span: crate::tokenizer::Span::empty(),
})
}
@@ -3376,6 +3392,7 @@ impl<'a> Parser<'a> {
Some(TokenWithLocation {
token: Token::Whitespace(_),
location: _,
+ span: _,
}) => continue,
token => {
return token
@@ -3402,6 +3419,7 @@ impl<'a> Parser<'a> {
if let Some(TokenWithLocation {
token: Token::Whitespace(_),
location: _,
+ span: _,
}) = self.tokens.get(self.index)
{
continue;
@@ -6819,6 +6837,7 @@ impl<'a> Parser<'a> {
TokenWithLocation {
token: Token::make_keyword(&name.to_string()),
location: next_token.location,
+ span: next_token.span,
},
);
}
@@ -7795,6 +7814,7 @@ impl<'a> Parser<'a> {
TokenWithLocation {
token: Token::Word(w),
location,
+ span: next_token.span,
},
)?,
},
@@ -7803,6 +7823,7 @@ impl<'a> Parser<'a> {
TokenWithLocation {
token: Token::Word(w),
location,
+ span: next_token.span,
},
),
},
@@ -7853,8 +7874,8 @@ impl<'a> Parser<'a> {
// This because snowflake allows numbers as placeholders
let next_token = self.next_token();
let ident = match next_token.token {
- Token::Word(w) => Ok(w.to_ident()),
- Token::Number(w, false) => Ok(Ident::new(w)),
+ Token::Word(w) => Ok(w.to_ident_with_span(next_token.span)),
+ Token::Number(w, false) => Ok(Ident::with_span(next_token.span, w)),
_ => self.expected("placeholder", next_token),
}?;
let placeholder = tok.to_string() + &ident.value;
@@ -7865,6 +7886,7 @@ impl<'a> Parser<'a> {
TokenWithLocation {
token: unexpected,
location,
+ span: location.span_to(location),
},
),
}
@@ -7914,6 +7936,7 @@ impl<'a> Parser<'a> {
TokenWithLocation {
token: unexpected,
location,
+ span: location.span_to(location),
},
),
}
@@ -8322,7 +8345,7 @@ impl<'a> Parser<'a> {
// (For example, in `FROM t1 JOIN` the `JOIN` will always be parsed as a keyword,
// not an alias.)
Token::Word(w) if after_as || !reserved_kwds.contains(&w.keyword) => {
- Ok(Some(w.to_ident()))
+ Ok(Some(w.to_ident_with_span(next_token.span)))
}
// MSSQL supports single-quoted strings as aliases for columns
// We accept them as table aliases too, although MSSQL does not.
@@ -8336,7 +8359,9 @@ impl<'a> Parser<'a> {
// character. When it sees such a <literal>, your DBMS will
// ignore the <separator> and treat the multiple strings as
// a single <literal>."
- Token::SingleQuotedString(s) => Ok(Some(Ident::with_quote('\'', s))),
+ Token::SingleQuotedString(s) => {
+ Ok(Some(Ident::with_quote_and_span('\'', next_token.span, s)))
+ }
// Support for MySql dialect double-quoted string, `AS "HOUR"` for example
Token::DoubleQuotedString(s) => Ok(Some(Ident::with_quote('\"', s))),
_ => {
@@ -8455,6 +8480,7 @@ impl<'a> Parser<'a> {
.map(|value| Ident {
value: value.into(),
quote_style: ident.quote_style,
+ span: ident.span,
})
.collect::<Vec<_>>()
})
@@ -8468,14 +8494,19 @@ impl<'a> Parser<'a> {
pub fn parse_identifiers(&mut self) -> Result<Vec<Ident>, ParserError> {
let mut idents = vec![];
loop {
- match self.peek_token().token {
- Token::Word(w) => {
- idents.push(w.to_ident());
+ let next = self.peek_token();
+ match next.token {
+ Token::Word(_) => {
+ let next = self.next_token();
+ if let Token::Word(w) = next.token {
+ idents.push(w.to_ident_with_span(next.span));
+ }
}
Token::EOF | Token::Eq => break,
- _ => {}
+ _ => {
+ self.next_token();
+ }
}
- self.next_token();
}
Ok(idents)
}
@@ -8523,8 +8554,9 @@ impl<'a> Parser<'a> {
let mut idents = vec![];
// expecting at least one word for identifier
- match self.next_token().token {
- Token::Word(w) => idents.push(w.to_ident()),
+ let next = self.next_token();
+ match next.token {
+ Token::Word(w) => idents.push(w.to_ident_with_span(next.span)),
Token::EOF => {
return Err(ParserError::ParserError(
"Empty input when parsing identifier".to_string(),
@@ -8541,8 +8573,12 @@ impl<'a> Parser<'a> {
loop {
match self.next_token().token {
// ensure that optional period is succeeded by another identifier
- Token::Period => match self.next_token().token {
- Token::Word(w) => idents.push(w.to_ident()),
+ Token::Period => match self.next_token() {
+ TokenWithLocation {
+ token: Token::Word(w),
+ span,
+ ..
+ } => idents.push(w.to_ident_with_span(span)),
Token::EOF => {
return Err(ParserError::ParserError(
"Trailing period in identifier".to_string(),
@@ -8575,7 +8611,7 @@ impl<'a> Parser<'a> {
let next_token = self.next_token();
match next_token.token {
Token::Word(w) => {
- let mut ident = w.to_ident();
+ let mut ident = w.to_ident_with_span(next_token.span);
// On BigQuery, hyphens are permitted in unquoted identifiers inside of a FROM or
// TABLE clause [0].
@@ -8601,10 +8637,12 @@ impl<'a> Parser<'a> {
requires_whitespace = match token.token {
Token::Word(next_word) if next_word.quote_style.is_none() => {
ident.value.push_str(&next_word.value);
+ ident.span = ident.span.union(&token.span);
false
}
Token::Number(s, false) if s.chars().all(|c| c.is_ascii_digit()) => {
ident.value.push_str(&s);
+ ident.span = ident.span.union(&token.span);
true
}
_ => {
@@ -8626,8 +8664,8 @@ impl<'a> Parser<'a> {
}
Ok(ident)
}
- Token::SingleQuotedString(s) => Ok(Ident::with_quote('\'', s)),
- Token::DoubleQuotedString(s) => Ok(Ident::with_quote('\"', s)),
+ Token::SingleQuotedString(s) => Ok(Ident::with_quote_and_span('\'', next_token.span, s)),
+ Token::DoubleQuotedString(s) => Ok(Ident::with_quote_and_span('\"', next_token.span, s)),
_ => self.expected("identifier", next_token),
}
}
@@ -12816,13 +12854,25 @@ impl Word {
Ident {
value: self.value.clone(),
quote_style: self.quote_style,
+ span: crate::tokenizer::Span::empty(),
+ }
+ }
+
+ pub fn to_ident_with_span(&self, span: crate::tokenizer::Span) -> Ident {
+ Ident {
+ value: self.value.clone(),
+ quote_style: self.quote_style,
+ span,
}
}
}
#[cfg(test)]
mod tests {
+ use crate::ast::Spanned;
+ use crate::dialect::GenericDialect;
use crate::test_utils::{all_dialects, TestedDialects};
+ use crate::tokenizer::{Span, Tokenizer};
use super::*;
@@ -12847,6 +12897,25 @@ mod tests {
});
}
+ #[test]
+ fn test_tokenizer_spans() {
+ let dialect = GenericDialect {};
+ let mut tokenizer = Tokenizer::new(&dialect, "SELECT a");
+ let tokens = tokenizer.tokenize_with_location().unwrap();
+ assert_eq!(tokens[0].span, Span::new((1, 1).into(), (1, 7).into()));
+ assert_eq!(tokens[2].span, Span::new((1, 8).into(), (1, 9).into()));
+ }
+
+ #[test]
+ fn test_statement_span_from_identifiers() {
+ let dialect = GenericDialect {};
+ let mut parser = Parser::new(&dialect)
+ .try_with_sql("SELECT a FROM table_1")
+ .unwrap();
+ let statement = parser.parse_statement().unwrap();
+ assert_eq!(statement.span(), Span::new((1, 8).into(), (1, 22).into()));
+ }
+
#[test]
fn test_peek_tokens() {
all_dialects().run_parser_method("SELECT foo AS bar FROM baz", |parser| {
@@ -13389,14 +13458,17 @@ mod tests {
Ident {
value: "CATALOG".to_string(),
quote_style: None,
+ span: Span::empty(),
},
Ident {
value: "F(o)o. \"bar".to_string(),
quote_style: Some('"'),
+ span: Span::empty(),
},
Ident {
value: "table".to_string(),
quote_style: None,
+ span: Span::empty(),
},
];
dialect.run_parser_method(r#"CATALOG."F(o)o. ""bar".table"#, |parser| {
@@ -13409,10 +13481,12 @@ mod tests {
Ident {
value: "CATALOG".to_string(),
quote_style: None,
+ span: Span::empty(),
},
Ident {
value: "table".to_string(),
quote_style: None,
+ span: Span::empty(),
},
];
dialect.run_parser_method("CATALOG . table", |parser| {
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/tokenizer.rs b/app/src/tokenizer.rs
index 05aaf1e..b8cb5fd 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/src/tokenizer.rs
+++ b/app/src/tokenizer.rs
@@ -29,6 +29,7 @@ use alloc::{
vec,
vec::Vec,
};
+use core::cmp;
use core::fmt;
use core::iter::Peekable;
use core::num::NonZeroU8;
@@ -444,11 +445,93 @@ impl fmt::Display for Location {
}
}
-/// A [Token] with [Location] attached to it
-#[derive(Debug, Eq, PartialEq, Clone)]
+impl Location {
+ /// Return an "empty" / unknown location.
+ pub const fn empty() -> Self {
+ Self { line: 0, column: 0 }
+ }
+
+ /// Create a new location for a given line and column.
+ pub const fn new(line: u64, column: u64) -> Self {
+ Self { line, column }
+ }
+
+ /// Combine self and `end` into a new span.
+ pub const fn span_to(self, end: Self) -> Span {
+ Span { start: self, end }
+ }
+}
+
+impl From<(u64, u64)> for Location {
+ fn from((line, column): (u64, u64)) -> Self {
+ Self { line, column }
+ }
+}
+
+/// A span represents a linear portion of the input string.
+#[derive(Eq, PartialEq, Hash, Clone, PartialOrd, Ord, Copy)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Span {
+ /// Start location (inclusive).
+ pub start: Location,
+ /// End location (exclusive).
+ pub end: Location,
+}
+
+impl fmt::Debug for Span {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Span({:?}..{:?})", self.start, self.end)
+ }
+}
+
+impl Span {
+ const EMPTY: Span = Self::empty();
+
+ /// Create a new span from a start and end location.
+ pub const fn new(start: Location, end: Location) -> Span {
+ Span { start, end }
+ }
+
+ /// Return an empty span.
+ pub const fn empty() -> Span {
+ Span {
+ start: Location::empty(),
+ end: Location::empty(),
+ }
+ }
+
+ /// Return the smallest span that contains both `self` and `other`.
+ pub fn union(&self, other: &Span) -> Span {
+ match (self, other) {
+ (&Span::EMPTY, _) => *other,
+ (_, &Span::EMPTY) => *self,
+ _ => Span {
+ start: cmp::min(self.start, other.start),
+ end: cmp::max(self.end, other.end),
+ },
+ }
+ }
+
+ /// Return the union of all spans in the iterator.
+ pub fn union_iter<I: IntoIterator<Item = Span>>(iter: I) -> Span {
+ iter.into_iter()
+ .reduce(|acc, item| acc.union(&item))
+ .unwrap_or_else(Span::empty)
+ }
+}
+
+/// A backwards-compatible alias for a token carrying source span information.
+pub type TokenWithSpan = TokenWithLocation;
+
+/// A [Token] with [Location] and [Span] attached to it
+#[derive(Debug, Eq, PartialEq, Clone, Hash, Ord, PartialOrd)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct TokenWithLocation {
pub token: Token,
pub location: Location,
+ pub span: Span,
}
impl TokenWithLocation {
@@ -456,12 +539,21 @@ impl TokenWithLocation {
TokenWithLocation {
token,
location: Location { line, column },
+ span: Span::new(Location { line, column }, Location { line, column }),
}
}
pub fn wrap(token: Token) -> TokenWithLocation {
TokenWithLocation::new(token, 0, 0)
}
+
+ pub fn with_span(token: Token, span: Span) -> TokenWithLocation {
+ TokenWithLocation {
+ token,
+ location: span.start,
+ span,
+ }
+ }
}
impl PartialEq<Token> for TokenWithLocation {
@@ -656,7 +748,12 @@ impl<'a> Tokenizer<'a> {
let mut location = state.location();
while let Some(token) = self.next_token(&mut state)? {
- buf.push(TokenWithLocation { token, location });
+ let span = Span::new(location, state.location());
+ buf.push(TokenWithLocation {
+ token,
+ location,
+ span,
+ });
location = state.location();
}
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_bigquery.rs b/app/tests/sqlparser_bigquery.rs
index d4c178b..bc118d0 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_bigquery.rs
+++ b/app/tests/sqlparser_bigquery.rs
@@ -678,10 +678,14 @@ fn parse_typed_struct_syntax_bigquery() {
Ident {
value: "t".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
Ident {
value: "str_col".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
]),
],
@@ -690,6 +694,8 @@ fn parse_typed_struct_syntax_bigquery() {
field_name: Some(Ident {
value: "x".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
field_type: DataType::Int64
},
@@ -697,6 +703,8 @@ fn parse_typed_struct_syntax_bigquery() {
field_name: Some(Ident {
value: "y".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
field_type: DataType::String(None)
},
@@ -709,6 +717,8 @@ fn parse_typed_struct_syntax_bigquery() {
values: vec![Expr::Identifier(Ident {
value: "nested_col".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),],
fields: vec![
StructField {
@@ -740,6 +750,8 @@ fn parse_typed_struct_syntax_bigquery() {
values: vec![Expr::Identifier(Ident {
value: "nested_col".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),],
fields: vec![
StructField {
@@ -987,10 +999,14 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
Ident {
value: "t".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
Ident {
value: "str_col".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
]),
],
@@ -999,6 +1015,8 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
field_name: Some(Ident {
value: "x".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
field_type: DataType::Int64
},
@@ -1006,6 +1024,8 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
field_name: Some(Ident {
value: "y".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
field_type: DataType::String(None)
},
@@ -1018,6 +1038,8 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
values: vec![Expr::Identifier(Ident {
value: "nested_col".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),],
fields: vec![
StructField {
@@ -1049,6 +1071,8 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
values: vec![Expr::Identifier(Ident {
value: "nested_col".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),],
fields: vec![
StructField {
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_clickhouse.rs b/app/tests/sqlparser_clickhouse.rs
index 90af12a..a9b0ea2 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_clickhouse.rs
+++ b/app/tests/sqlparser_clickhouse.rs
@@ -45,6 +45,8 @@ fn parse_map_access_expr() {
column: Box::new(Identifier(Ident {
value: "string_values".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
keys: vec![MapAccessKey {
key: call(
@@ -903,7 +905,8 @@ fn parse_create_view_with_fields_data_types() {
data_type: Some(DataType::Custom(
ObjectName(vec![Ident {
value: "int".into(),
- quote_style: Some('"')
+ quote_style: Some('"'),
+ span: Span::empty(),
}]),
vec![]
)),
@@ -914,7 +917,8 @@ fn parse_create_view_with_fields_data_types() {
data_type: Some(DataType::Custom(
ObjectName(vec![Ident {
value: "String".into(),
- quote_style: Some('"')
+ quote_style: Some('"'),
+ span: Span::empty(),
}]),
vec![]
)),
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_common.rs b/app/tests/sqlparser_common.rs
index e22877d..efc25cf 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_common.rs
+++ b/app/tests/sqlparser_common.rs
@@ -1271,6 +1271,8 @@ fn parse_select_with_date_column_name() {
&Expr::Identifier(Ident {
value: "date".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
expr_from_projection(only(&select.projection)),
);
@@ -1789,6 +1791,8 @@ fn parse_null_like() {
alias: Ident {
value: "col_null".to_owned(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
},
select.projection[0]
@@ -1805,6 +1809,8 @@ fn parse_null_like() {
alias: Ident {
value: "null_col".to_owned(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
},
select.projection[1]
@@ -2823,6 +2829,8 @@ fn parse_listagg() {
expr: Expr::Identifier(Ident {
value: "id".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
asc: None,
nulls_first: None,
@@ -2832,6 +2840,8 @@ fn parse_listagg() {
expr: Expr::Identifier(Ident {
value: "username".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
asc: None,
nulls_first: None,
@@ -4038,7 +4048,8 @@ fn parse_alter_table() {
[SqlOption::KeyValue {
key: Ident {
value: "classification".to_string(),
- quote_style: Some('\'')
+ quote_style: Some('\''),
+ span: Span::empty(),
},
value: Expr::Value(Value::SingleQuotedString("parquet".to_string())),
}],
@@ -4833,6 +4844,8 @@ fn test_parse_named_window() {
name: ObjectName(vec![Ident {
value: "MIN".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}]),
parameters: FunctionArguments::None,
args: FunctionArguments::List(FunctionArgumentList {
@@ -4841,6 +4854,8 @@ fn test_parse_named_window() {
Expr::Identifier(Ident {
value: "c12".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
))],
clauses: vec![],
@@ -4850,12 +4865,16 @@ fn test_parse_named_window() {
over: Some(WindowType::NamedWindow(Ident {
value: "window1".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
within_group: vec![],
}),
alias: Ident {
value: "min1".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
},
SelectItem::ExprWithAlias {
@@ -4863,6 +4882,8 @@ fn test_parse_named_window() {
name: ObjectName(vec![Ident {
value: "MAX".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}]),
parameters: FunctionArguments::None,
args: FunctionArguments::List(FunctionArgumentList {
@@ -4871,6 +4892,8 @@ fn test_parse_named_window() {
Expr::Identifier(Ident {
value: "c12".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
))],
clauses: vec![],
@@ -4880,12 +4903,16 @@ fn test_parse_named_window() {
over: Some(WindowType::NamedWindow(Ident {
value: "window2".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
within_group: vec![],
}),
alias: Ident {
value: "max1".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
},
],
@@ -4895,6 +4922,8 @@ fn test_parse_named_window() {
name: ObjectName(vec![Ident {
value: "aggregate_test_100".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}]),
alias: None,
args: None,
@@ -4919,6 +4948,8 @@ fn test_parse_named_window() {
Ident {
value: "window1".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
NamedWindowExpr::WindowSpec(WindowSpec {
window_name: None,
@@ -4927,6 +4958,8 @@ fn test_parse_named_window() {
expr: Expr::Identifier(Ident {
value: "C12".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
asc: None,
nulls_first: None,
@@ -4939,12 +4972,16 @@ fn test_parse_named_window() {
Ident {
value: "window2".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
NamedWindowExpr::WindowSpec(WindowSpec {
window_name: None,
partition_by: vec![Expr::Identifier(Ident {
value: "C11".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})],
order_by: vec![],
window_frame: None,
@@ -5425,6 +5462,8 @@ fn interval_disallow_interval_expr_gt() {
right: Box::new(Expr::Identifier(Ident {
value: "x".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
}
)
@@ -5471,6 +5510,8 @@ fn parse_interval_and_or_xor() {
projection: vec![UnnamedExpr(Expr::Identifier(Ident {
value: "col".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}))],
into: None,
from: vec![TableWithJoins {
@@ -5478,6 +5519,8 @@ fn parse_interval_and_or_xor() {
name: ObjectName(vec![Ident {
value: "test".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}]),
alias: None,
args: None,
@@ -5496,12 +5539,16 @@ fn parse_interval_and_or_xor() {
left: Box::new(Expr::Identifier(Ident {
value: "d3_date".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
op: BinaryOperator::Gt,
right: Box::new(Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident {
value: "d1_date".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
op: BinaryOperator::Plus,
right: Box::new(Expr::Interval(Interval {
@@ -5520,12 +5567,16 @@ fn parse_interval_and_or_xor() {
left: Box::new(Expr::Identifier(Ident {
value: "d2_date".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
op: BinaryOperator::Gt,
right: Box::new(Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident {
value: "d1_date".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
op: BinaryOperator::Plus,
right: Box::new(Expr::Interval(Interval {
@@ -5617,6 +5668,8 @@ fn parse_at_timezone() {
alias: Ident {
value: "hour".to_string(),
quote_style: Some('"'),
+ span: Span::empty(),
+ span: Span::empty(),
},
},
only(&select.projection),
@@ -6637,6 +6690,8 @@ fn parse_recursive_cte() {
name: Ident {
value: "nums".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
columns: vec![TableAliasColumnDef::from_name("val")],
},
@@ -7632,6 +7687,8 @@ fn lateral_function() {
name: ObjectName(vec![Ident {
value: "customer".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}]),
alias: None,
args: None,
@@ -8270,10 +8327,14 @@ fn parse_grant() {
Ident {
value: "shape".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
Ident {
value: "size".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
])
},
@@ -8515,6 +8576,8 @@ fn parse_merge() {
name: Ident {
value: "stg".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
columns: vec![],
}),
@@ -8714,7 +8777,8 @@ fn test_lock_table() {
lock.of.unwrap().0,
vec![Ident {
value: "school".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]
);
assert!(lock.nonblock.is_none());
@@ -8728,7 +8792,8 @@ fn test_lock_table() {
lock.of.unwrap().0,
vec![Ident {
value: "school".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]
);
assert!(lock.nonblock.is_none());
@@ -8742,7 +8807,8 @@ fn test_lock_table() {
lock.of.unwrap().0,
vec![Ident {
value: "school".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]
);
assert!(lock.nonblock.is_none());
@@ -8752,7 +8818,8 @@ fn test_lock_table() {
lock.of.unwrap().0,
vec![Ident {
value: "student".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]
);
assert!(lock.nonblock.is_none());
@@ -8769,7 +8836,8 @@ fn test_lock_nonblock() {
lock.of.unwrap().0,
vec![Ident {
value: "school".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]
);
assert_eq!(lock.nonblock.unwrap(), NonBlock::SkipLocked);
@@ -8783,7 +8851,8 @@ fn test_lock_nonblock() {
lock.of.unwrap().0,
vec![Ident {
value: "school".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]
);
assert_eq!(lock.nonblock.unwrap(), NonBlock::Nowait);
@@ -9584,7 +9653,8 @@ fn parse_pivot_table() {
alias: Some(TableAlias {
name: Ident {
value: "p".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![
TableAliasColumnDef::from_name("c"),
@@ -9636,12 +9706,14 @@ fn parse_unpivot_table() {
}),
value: Ident {
value: "quantity".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
name: Ident {
value: "quarter".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: ["Q1", "Q2", "Q3", "Q4"]
.into_iter()
@@ -9704,12 +9776,14 @@ fn parse_pivot_unpivot_table() {
}),
value: Ident {
value: "population".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
name: Ident {
value: "year".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: ["population_2000", "population_2010"]
.into_iter()
@@ -9999,10 +10073,14 @@ fn parse_execute_stored_procedure() {
Ident {
value: "my_schema".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
Ident {
value: "my_stored_procedure".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
]),
parameters: vec![
@@ -10143,12 +10221,14 @@ fn parse_unload() {
}),
to: Ident {
value: "s3://...".to_string(),
- quote_style: Some('\'')
+ quote_style: Some('\''),
+ span: Span::empty(),
},
with: vec![SqlOption::KeyValue {
key: Ident {
value: "format".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
value: Expr::Value(Value::SingleQuotedString("AVRO".to_string()))
}]
@@ -11206,6 +11286,8 @@ fn test_extract_seconds_ok() {
field: DateTimeField::Custom(Ident {
value: "seconds".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}),
syntax: ExtractSyntax::From,
expr: Box::new(Expr::Cast {
@@ -11231,6 +11313,8 @@ fn test_extract_seconds_single_quote_ok() {
field: DateTimeField::Custom(Ident {
value: "seconds".to_string(),
quote_style: Some('\''),
+ span: Span::empty(),
+ span: Span::empty(),
}),
syntax: ExtractSyntax::From,
expr: Box::new(Expr::Cast {
@@ -12130,7 +12214,8 @@ fn test_load_extension() {
assert_eq!(
Ident {
value: "filename".to_string(),
- quote_style: Some('\'')
+ quote_style: Some('\''),
+ span: Span::empty(),
},
extension_name
);
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_duckdb.rs b/app/tests/sqlparser_duckdb.rs
index 73b0f66..364fce1 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_duckdb.rs
+++ b/app/tests/sqlparser_duckdb.rs
@@ -275,6 +275,8 @@ fn test_select_union_by_name() {
name: ObjectName(vec![Ident {
value: "capitals".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}]),
alias: None,
args: None,
@@ -317,6 +319,8 @@ fn test_select_union_by_name() {
name: ObjectName(vec![Ident {
value: "weather".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}]),
alias: None,
args: None,
@@ -355,7 +359,8 @@ fn test_duckdb_install() {
Statement::Install {
extension_name: Ident {
value: "tpch".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}
}
);
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_mssql.rs b/app/tests/sqlparser_mssql.rs
index d1d8d12..ca016db 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_mssql.rs
+++ b/app/tests/sqlparser_mssql.rs
@@ -138,14 +138,16 @@ fn parse_create_procedure() {
ProcedureParam {
name: Ident {
value: "@foo".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
data_type: DataType::Int(None)
},
ProcedureParam {
name: Ident {
value: "@bar".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
data_type: DataType::Varchar(Some(CharacterLength::IntegerLength {
length: 256,
@@ -155,7 +157,8 @@ fn parse_create_procedure() {
]),
name: ObjectName(vec![Ident {
value: "test".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}])
}
)
@@ -207,11 +210,14 @@ fn parse_mssql_openjson() {
name: ObjectName(vec![Ident {
value: "t_test_table".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},]),
alias: Some(TableAlias {
name: Ident {
value: "A".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
}),
@@ -228,10 +234,14 @@ fn parse_mssql_openjson() {
Ident {
value: "A".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
Ident {
value: "param".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}
]),
json_path: Some(Value::SingleQuotedString("$.config".into())),
@@ -240,6 +250,8 @@ fn parse_mssql_openjson() {
name: Ident {
value: "kind".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
r#type: DataType::Varchar(Some(CharacterLength::IntegerLength {
length: 20,
@@ -252,6 +264,8 @@ fn parse_mssql_openjson() {
name: Ident {
value: "id_list".into(),
quote_style: Some('['),
+ span: Span::empty(),
+ span: Span::empty(),
},
r#type: DataType::Nvarchar(Some(CharacterLength::Max)),
path: Some("$.id_list".into()),
@@ -261,7 +275,8 @@ fn parse_mssql_openjson() {
alias: Some(TableAlias {
name: Ident {
value: "B".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
})
@@ -283,11 +298,14 @@ fn parse_mssql_openjson() {
name: ObjectName(vec![Ident {
value: "t_test_table".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},]),
alias: Some(TableAlias {
name: Ident {
value: "A".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
}),
@@ -304,10 +322,14 @@ fn parse_mssql_openjson() {
Ident {
value: "A".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
Ident {
value: "param".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}
]),
json_path: None,
@@ -316,6 +338,8 @@ fn parse_mssql_openjson() {
name: Ident {
value: "kind".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
r#type: DataType::Varchar(Some(CharacterLength::IntegerLength {
length: 20,
@@ -328,6 +352,8 @@ fn parse_mssql_openjson() {
name: Ident {
value: "id_list".into(),
quote_style: Some('['),
+ span: Span::empty(),
+ span: Span::empty(),
},
r#type: DataType::Nvarchar(Some(CharacterLength::Max)),
path: Some("$.id_list".into()),
@@ -337,7 +363,8 @@ fn parse_mssql_openjson() {
alias: Some(TableAlias {
name: Ident {
value: "B".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
})
@@ -359,11 +386,14 @@ fn parse_mssql_openjson() {
name: ObjectName(vec![Ident {
value: "t_test_table".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},]),
alias: Some(TableAlias {
name: Ident {
value: "A".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
}),
@@ -380,10 +410,14 @@ fn parse_mssql_openjson() {
Ident {
value: "A".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
Ident {
value: "param".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}
]),
json_path: None,
@@ -392,6 +426,8 @@ fn parse_mssql_openjson() {
name: Ident {
value: "kind".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
r#type: DataType::Varchar(Some(CharacterLength::IntegerLength {
length: 20,
@@ -404,6 +440,8 @@ fn parse_mssql_openjson() {
name: Ident {
value: "id_list".into(),
quote_style: Some('['),
+ span: Span::empty(),
+ span: Span::empty(),
},
r#type: DataType::Nvarchar(Some(CharacterLength::Max)),
path: None,
@@ -413,7 +451,8 @@ fn parse_mssql_openjson() {
alias: Some(TableAlias {
name: Ident {
value: "B".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
})
@@ -435,11 +474,14 @@ fn parse_mssql_openjson() {
name: ObjectName(vec![Ident {
value: "t_test_table".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},]),
alias: Some(TableAlias {
name: Ident {
value: "A".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
}),
@@ -456,10 +498,14 @@ fn parse_mssql_openjson() {
Ident {
value: "A".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
Ident {
value: "param".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}
]),
json_path: Some(Value::SingleQuotedString("$.config".into())),
@@ -467,7 +513,8 @@ fn parse_mssql_openjson() {
alias: Some(TableAlias {
name: Ident {
value: "B".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
})
@@ -489,11 +536,14 @@ fn parse_mssql_openjson() {
name: ObjectName(vec![Ident {
value: "t_test_table".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},]),
alias: Some(TableAlias {
name: Ident {
value: "A".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
}),
@@ -510,10 +560,14 @@ fn parse_mssql_openjson() {
Ident {
value: "A".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
Ident {
value: "param".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
}
]),
json_path: None,
@@ -521,7 +575,8 @@ fn parse_mssql_openjson() {
alias: Some(TableAlias {
name: Ident {
value: "B".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
columns: vec![]
})
@@ -607,7 +662,8 @@ fn parse_mssql_create_role() {
authorization_owner,
Some(ObjectName(vec![Ident {
value: "helena".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]))
);
}
@@ -623,12 +679,14 @@ fn parse_alter_role() {
[Statement::AlterRole {
name: Ident {
value: "old_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::RenameRole {
role_name: Ident {
value: "new_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}
},
}]
@@ -640,12 +698,14 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::AddMember {
member_name: Ident {
value: "new_member".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}
},
}
@@ -657,12 +717,14 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::DropMember {
member_name: Ident {
value: "old_member".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}
},
}
@@ -1143,7 +1205,8 @@ fn parse_substring_in_select() {
projection: vec![SelectItem::UnnamedExpr(Expr::Substring {
expr: Box::new(Expr::Identifier(Ident {
value: "description".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
})),
substring_from: Some(Box::new(Expr::Value(number("0")))),
substring_for: Some(Box::new(Expr::Value(number("1")))),
@@ -1154,7 +1217,8 @@ fn parse_substring_in_select() {
relation: TableFactor::Table {
name: ObjectName(vec![Ident {
value: "test".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
alias: None,
args: None,
@@ -1208,7 +1272,8 @@ fn parse_mssql_declare() {
Declare {
names: vec![Ident {
value: "@foo".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}],
data_type: None,
assignment: None,
@@ -1222,7 +1287,8 @@ fn parse_mssql_declare() {
Declare {
names: vec![Ident {
value: "@bar".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}],
data_type: Some(Int(None)),
assignment: None,
@@ -1236,7 +1302,8 @@ fn parse_mssql_declare() {
Declare {
names: vec![Ident {
value: "@baz".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}],
data_type: Some(Text),
assignment: Some(MsSqlAssignment(Box::new(Expr::Value(SingleQuotedString(
@@ -1262,7 +1329,8 @@ fn parse_mssql_declare() {
stmts: vec![Declare {
names: vec![Ident {
value: "@bar".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}],
data_type: Some(Int(None)),
assignment: None,
@@ -1364,10 +1432,14 @@ fn parse_create_table_with_valid_options() {
key: Ident {
value: "DISTRIBUTION".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
value: Expr::Identifier(Ident {
value: "ROUND_ROBIN".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})
},
SqlOption::Partition {
@@ -1411,6 +1483,8 @@ fn parse_create_table_with_valid_options() {
name: Ident {
value: "column_a".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
asc: Some(true),
},
@@ -1418,6 +1492,8 @@ fn parse_create_table_with_valid_options() {
name: Ident {
value: "column_b".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
asc: Some(false),
},
@@ -1425,6 +1501,8 @@ fn parse_create_table_with_valid_options() {
name: Ident {
value: "column_c".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
asc: None,
},
@@ -1438,6 +1516,8 @@ fn parse_create_table_with_valid_options() {
key: Ident {
value: "DISTRIBUTION".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
value: Expr::Function(
Function {
@@ -1446,6 +1526,8 @@ fn parse_create_table_with_valid_options() {
Ident {
value: "HASH".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
],
),
@@ -1460,6 +1542,8 @@ fn parse_create_table_with_valid_options() {
Ident {
value: "column_a".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
),
),
@@ -1470,6 +1554,8 @@ fn parse_create_table_with_valid_options() {
Ident {
value: "column_b".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
),
),
@@ -1504,12 +1590,16 @@ fn parse_create_table_with_valid_options() {
name: ObjectName(vec![Ident {
value: "mytable".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},],),
columns: vec![
ColumnDef {
name: Ident {
value: "column_a".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
data_type: Int(None,),
collation: None,
@@ -1519,6 +1609,8 @@ fn parse_create_table_with_valid_options() {
name: Ident {
value: "column_b".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
data_type: Int(None,),
collation: None,
@@ -1528,6 +1620,8 @@ fn parse_create_table_with_valid_options() {
name: Ident {
value: "column_c".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
data_type: Int(None,),
collation: None,
@@ -1669,11 +1763,15 @@ fn parse_create_table_with_identity_column() {
name: ObjectName(vec![Ident {
value: "mytable".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},],),
columns: vec![ColumnDef {
name: Ident {
value: "columnA".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
data_type: Int(None,),
collation: None,
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_mysql.rs b/app/tests/sqlparser_mysql.rs
index 3d8b086..c2718eb 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_mysql.rs
+++ b/app/tests/sqlparser_mysql.rs
@@ -142,16 +142,19 @@ fn parse_flush() {
ObjectName(vec![
Ident {
value: "mek".to_string(),
- quote_style: Some('`')
+ quote_style: Some('`'),
+ span: Span::empty(),
},
Ident {
value: "table1".to_string(),
- quote_style: Some('`')
+ quote_style: Some('`'),
+ span: Span::empty(),
}
]),
ObjectName(vec![Ident {
value: "table2".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}])
]
}
@@ -179,16 +182,19 @@ fn parse_flush() {
ObjectName(vec![
Ident {
value: "mek".to_string(),
- quote_style: Some('`')
+ quote_style: Some('`'),
+ span: Span::empty(),
},
Ident {
value: "table1".to_string(),
- quote_style: Some('`')
+ quote_style: Some('`'),
+ span: Span::empty(),
}
]),
ObjectName(vec![Ident {
value: "table2".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}])
]
}
@@ -205,16 +211,19 @@ fn parse_flush() {
ObjectName(vec![
Ident {
value: "mek".to_string(),
- quote_style: Some('`')
+ quote_style: Some('`'),
+ span: Span::empty(),
},
Ident {
value: "table1".to_string(),
- quote_style: Some('`')
+ quote_style: Some('`'),
+ span: Span::empty(),
}
]),
ObjectName(vec![Ident {
value: "table2".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}])
]
}
@@ -1064,6 +1073,8 @@ fn parse_escaped_quote_identifiers_with_escape() {
projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident {
value: "quoted ` identifier".into(),
quote_style: Some('`'),
+ span: Span::empty(),
+ span: Span::empty(),
}))],
into: None,
from: vec![],
@@ -1115,6 +1126,8 @@ fn parse_escaped_quote_identifiers_with_no_escape() {
projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident {
value: "quoted `` identifier".into(),
quote_style: Some('`'),
+ span: Span::empty(),
+ span: Span::empty(),
}))],
into: None,
from: vec![],
@@ -1159,6 +1172,8 @@ fn parse_escaped_backticks_with_escape() {
projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident {
value: "`quoted identifier`".into(),
quote_style: Some('`'),
+ span: Span::empty(),
+ span: Span::empty(),
}))],
into: None,
from: vec![],
@@ -1207,6 +1222,8 @@ fn parse_escaped_backticks_with_no_escape() {
projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident {
value: "``quoted identifier``".into(),
quote_style: Some('`'),
+ span: Span::empty(),
+ span: Span::empty(),
}))],
into: None,
from: vec![],
@@ -2055,7 +2072,8 @@ fn parse_delete_with_order_by() {
vec![OrderByExpr {
expr: Expr::Identifier(Ident {
value: "id".to_owned(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}),
asc: Some(false),
nulls_first: None,
@@ -2136,7 +2154,8 @@ fn parse_alter_table_add_column() {
},
column_position: Some(MySQLColumnPosition::After(Ident {
value: String::from("foo"),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
})),
},]
);
@@ -2187,6 +2206,8 @@ fn parse_alter_table_add_columns() {
column_position: Some(MySQLColumnPosition::After(Ident {
value: String::from("foo"),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
},
]
@@ -2247,6 +2268,8 @@ fn parse_alter_table_change_column() {
column_position: Some(MySQLColumnPosition::After(Ident {
value: String::from("foo"),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
};
let sql4 = "ALTER TABLE orders CHANGE COLUMN description desc TEXT NOT NULL AFTER foo";
@@ -2286,6 +2309,8 @@ fn parse_alter_table_change_column_with_column_position() {
column_position: Some(MySQLColumnPosition::After(Ident {
value: String::from("total_count"),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
};
@@ -2342,6 +2367,8 @@ fn parse_alter_table_modify_column() {
column_position: Some(MySQLColumnPosition::After(Ident {
value: String::from("foo"),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
};
let sql4 = "ALTER TABLE orders MODIFY COLUMN description TEXT NOT NULL AFTER foo";
@@ -2379,6 +2406,8 @@ fn parse_alter_table_modify_column_with_column_position() {
column_position: Some(MySQLColumnPosition::After(Ident {
value: String::from("total_count"),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
};
@@ -2413,7 +2442,8 @@ fn parse_substring_in_select() {
projection: vec![SelectItem::UnnamedExpr(Expr::Substring {
expr: Box::new(Expr::Identifier(Ident {
value: "description".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
})),
substring_from: Some(Box::new(Expr::Value(number("0")))),
substring_for: Some(Box::new(Expr::Value(number("1")))),
@@ -2424,7 +2454,8 @@ fn parse_substring_in_select() {
relation: TableFactor::Table {
name: ObjectName(vec![Ident {
value: "test".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
alias: None,
args: None,
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_postgres.rs b/app/tests/sqlparser_postgres.rs
index d27569e..6a27817 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_postgres.rs
+++ b/app/tests/sqlparser_postgres.rs
@@ -1172,6 +1172,8 @@ fn parse_copy_to() {
alias: Ident {
value: "a".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
},
SelectItem::ExprWithAlias {
@@ -1179,6 +1181,8 @@ fn parse_copy_to() {
alias: Ident {
value: "b".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
}
],
@@ -1318,7 +1322,8 @@ fn parse_set() {
variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a")])),
value: vec![Expr::Identifier(Ident {
value: "b".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
})],
}
);
@@ -1380,7 +1385,8 @@ fn parse_set() {
])),
value: vec![Expr::Identifier(Ident {
value: "b".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
})],
}
);
@@ -1452,6 +1458,8 @@ fn parse_set_role() {
role_name: Some(Ident {
value: "rolename".to_string(),
quote_style: Some('\"'),
+ span: Span::empty(),
+ span: Span::empty(),
}),
}
);
@@ -1466,6 +1474,8 @@ fn parse_set_role() {
role_name: Some(Ident {
value: "rolename".to_string(),
quote_style: Some('\''),
+ span: Span::empty(),
+ span: Span::empty(),
}),
}
);
@@ -1765,7 +1775,8 @@ fn parse_pg_on_conflict() {
selection: Some(Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident {
value: "dsize".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
})),
op: BinaryOperator::Gt,
right: Box::new(Expr::Value(Value::Placeholder("$2".to_string())))
@@ -1802,7 +1813,8 @@ fn parse_pg_on_conflict() {
selection: Some(Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident {
value: "dsize".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
})),
op: BinaryOperator::Gt,
right: Box::new(Expr::Value(Value::Placeholder("$2".to_string())))
@@ -2105,14 +2117,16 @@ fn parse_array_index_expr() {
subscript: Box::new(Subscript::Index {
index: Expr::Identifier(Ident {
value: "baz".to_string(),
- quote_style: Some('"')
+ quote_style: Some('"'),
+ span: Span::empty(),
})
})
}),
subscript: Box::new(Subscript::Index {
index: Expr::Identifier(Ident {
value: "fooz".to_string(),
- quote_style: Some('"')
+ quote_style: Some('"'),
+ span: Span::empty(),
})
})
},
@@ -3123,6 +3137,8 @@ fn parse_custom_operator() {
left: Box::new(Expr::Identifier(Ident {
value: "relname".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
op: BinaryOperator::PGCustomBinaryOperator(vec![
"database".into(),
@@ -3142,6 +3158,8 @@ fn parse_custom_operator() {
left: Box::new(Expr::Identifier(Ident {
value: "relname".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
op: BinaryOperator::PGCustomBinaryOperator(vec!["pg_catalog".into(), "~".into()]),
right: Box::new(Expr::Value(Value::SingleQuotedString("^(table)$".into())))
@@ -3157,6 +3175,8 @@ fn parse_custom_operator() {
left: Box::new(Expr::Identifier(Ident {
value: "relname".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
op: BinaryOperator::PGCustomBinaryOperator(vec!["~".into()]),
right: Box::new(Expr::Value(Value::SingleQuotedString("^(table)$".into())))
@@ -3307,12 +3327,14 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "old_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::RenameRole {
role_name: Ident {
value: "new_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}
},
}
@@ -3324,7 +3346,8 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::WithOptions {
options: vec![
@@ -3353,7 +3376,8 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::WithOptions {
options: vec![
@@ -3376,12 +3400,14 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::Set {
config_name: ObjectName(vec![Ident {
value: "maintenance_work_mem".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
config_value: SetConfigValue::FromCurrent,
in_database: None
@@ -3395,17 +3421,20 @@ fn parse_alter_role() {
[Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::Set {
config_name: ObjectName(vec![Ident {
value: "maintenance_work_mem".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
config_value: SetConfigValue::Value(Expr::Value(number("100000"))),
in_database: Some(ObjectName(vec![Ident {
value: "database_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]))
},
}]
@@ -3417,17 +3446,20 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::Set {
config_name: ObjectName(vec![Ident {
value: "maintenance_work_mem".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
config_value: SetConfigValue::Value(Expr::Value(number("100000"))),
in_database: Some(ObjectName(vec![Ident {
value: "database_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]))
},
}
@@ -3439,17 +3471,20 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::Set {
config_name: ObjectName(vec![Ident {
value: "maintenance_work_mem".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
config_value: SetConfigValue::Default,
in_database: Some(ObjectName(vec![Ident {
value: "database_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]))
},
}
@@ -3461,7 +3496,8 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::Reset {
config_name: ResetConfig::ALL,
@@ -3476,16 +3512,19 @@ fn parse_alter_role() {
Statement::AlterRole {
name: Ident {
value: "role_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
operation: AlterRoleOperation::Reset {
config_name: ResetConfig::ConfigName(ObjectName(vec![Ident {
value: "maintenance_work_mem".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}])),
in_database: Some(ObjectName(vec![Ident {
value: "database_name".into(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]))
},
}
@@ -3630,7 +3669,8 @@ fn parse_drop_function() {
func_desc: vec![FunctionDesc {
name: ObjectName(vec![Ident {
value: "test_func".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
args: None
}],
@@ -3646,7 +3686,8 @@ fn parse_drop_function() {
func_desc: vec![FunctionDesc {
name: ObjectName(vec![Ident {
value: "test_func".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
args: Some(vec![
OperateFunctionArg::with_name("a", DataType::Integer(None)),
@@ -3671,7 +3712,8 @@ fn parse_drop_function() {
FunctionDesc {
name: ObjectName(vec![Ident {
value: "test_func1".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
args: Some(vec![
OperateFunctionArg::with_name("a", DataType::Integer(None)),
@@ -3689,7 +3731,8 @@ fn parse_drop_function() {
FunctionDesc {
name: ObjectName(vec![Ident {
value: "test_func2".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
args: Some(vec![
OperateFunctionArg::with_name("a", DataType::Varchar(None)),
@@ -3720,7 +3763,8 @@ fn parse_drop_procedure() {
proc_desc: vec![FunctionDesc {
name: ObjectName(vec![Ident {
value: "test_proc".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
args: None
}],
@@ -3736,7 +3780,8 @@ fn parse_drop_procedure() {
proc_desc: vec![FunctionDesc {
name: ObjectName(vec![Ident {
value: "test_proc".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
args: Some(vec![
OperateFunctionArg::with_name("a", DataType::Integer(None)),
@@ -3761,7 +3806,8 @@ fn parse_drop_procedure() {
FunctionDesc {
name: ObjectName(vec![Ident {
value: "test_proc1".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
args: Some(vec![
OperateFunctionArg::with_name("a", DataType::Integer(None)),
@@ -3779,7 +3825,8 @@ fn parse_drop_procedure() {
FunctionDesc {
name: ObjectName(vec![Ident {
value: "test_proc2".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
args: Some(vec![
OperateFunctionArg::with_name("a", DataType::Varchar(None)),
@@ -3860,6 +3907,8 @@ fn parse_dollar_quoted_string() {
alias: Ident {
value: "col_name".into(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
},
}
);
@@ -4204,20 +4253,24 @@ fn test_simple_postgres_insert_with_alias() {
into: true,
table_name: ObjectName(vec![Ident {
value: "test_tables".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
table_alias: Some(Ident {
value: "test_table".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}),
columns: vec![
Ident {
value: "id".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
Ident {
value: "a".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}
],
overwrite: false,
@@ -4267,20 +4320,24 @@ fn test_simple_postgres_insert_with_alias() {
into: true,
table_name: ObjectName(vec![Ident {
value: "test_tables".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
table_alias: Some(Ident {
value: "test_table".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}),
columns: vec![
Ident {
value: "id".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
Ident {
value: "a".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}
],
overwrite: false,
@@ -4332,20 +4389,24 @@ fn test_simple_insert_with_quoted_alias() {
into: true,
table_name: ObjectName(vec![Ident {
value: "test_tables".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}]),
table_alias: Some(Ident {
value: "Test_Table".to_string(),
- quote_style: Some('"')
+ quote_style: Some('"'),
+ span: Span::empty(),
}),
columns: vec![
Ident {
value: "id".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
},
Ident {
value: "a".to_string(),
- quote_style: None
+ quote_style: None,
+ span: Span::empty(),
}
],
overwrite: false,
@@ -5017,6 +5078,8 @@ fn check_arrow_precedence(sql: &str, arrow_operator: BinaryOperator) {
left: Box::new(Expr::Identifier(Ident {
value: "foo".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
op: arrow_operator,
right: Box::new(Expr::Value(Value::SingleQuotedString("bar".to_string()))),
@@ -5047,6 +5110,8 @@ fn arrow_cast_precedence() {
left: Box::new(Expr::Identifier(Ident {
value: "foo".to_string(),
quote_style: None,
+ span: Span::empty(),
+ span: Span::empty(),
})),
op: BinaryOperator::Arrow,
right: Box::new(Expr::Cast {
diff --git a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_redshift.rs b/app/tests/sqlparser_redshift.rs
index 0a084b3..b1285a3 100644
--- a/tmp/agent-patch-flux-pr-1435.1-of-1.2026-02-28__18-27-22__gpt-5-4/app/tests/sqlparser_redshift.rs
+++ b/app/tests/sqlparser_redshift.rs
@@ -31,7 +31,8 @@ fn test_square_brackets_over_db_schema_table_name() {
select.projection[0],
SelectItem::UnnamedExpr(Expr::Identifier(Ident {
value: "col1".to_string(),
- quote_style: Some('[')
+ quote_style: Some('['),
+ span: Span::empty(),
})),
);
assert_eq!(
@@ -41,11 +42,13 @@ fn test_square_brackets_over_db_schema_table_name() {
name: ObjectName(vec![
Ident {
value: "test_schema".to_string(),
- quote_style: Some('[')
+ quote_style: Some('['),
+ span: Span::empty(),
},
Ident {
value: "test_table".to_string(),
- quote_style: Some('[')
+ quote_style: Some('['),
+ span: Span::empty(),
}
]),
alias: None,
@@ -79,7 +82,8 @@ fn test_double_quotes_over_db_schema_table_name() {
select.projection[0],
SelectItem::UnnamedExpr(Expr::Identifier(Ident {
value: "col1".to_string(),
- quote_style: Some('"')
+ quote_style: Some('"'),
+ span: Span::empty(),
})),
);
assert_eq!(
@@ -89,11 +93,13 @@ fn test_double_quotes_over_db_schema_table_name() {
name: ObjectName(vec![
Ident {
value: "test_schema".to_string(),
- quote_style: Some('"')
+ quote_style: Some('"'),
+ span: Span::empty(),
},
Ident {
value: "test_table".to_string(),
- quote_style: Some('"')
+ quote_style: Some('"'),
+ span: Span::empty(),
}
]),
alias: None,