Skip to content

Add parsing of alter column in alter statements #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 11, 2024
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sql-parse"
version = "0.21.0"
version = "0.22.0"
edition = "2021"
authors = ["Jakob Truelsen <[email protected]>"]
keywords = [ "mysql", "postgresql", "sql", "lexer", "parser" ]
Expand Down
159 changes: 154 additions & 5 deletions src/alter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ use alloc::vec::Vec;
// limitations under the License.
use crate::{
data_type::parse_data_type,
expression::parse_expression,
keywords::Keyword,
lexer::Token,
parser::{ParseError, Parser},
qualified_name::parse_qualified_name,
DataType, Identifier, QualifiedName, SString, Span, Spanned, Statement,
DataType, Expression, Identifier, QualifiedName, SString, Span, Spanned, Statement,
};

/// Option on an index
Expand Down Expand Up @@ -132,6 +133,43 @@ impl<'a> Spanned for IndexCol<'a> {
}
}

/// Enum of alterations to perform on a column
#[derive(Clone, Debug)]
pub enum AlterColumnAction<'a> {
SetDefault {
set_default_span: Span,
value: Expression<'a>,
},
DropDefault {
drop_default_span: Span,
},
Type {
type_span: Span,
type_: DataType<'a>,
},
SetNotNull {
set_not_null_span: Span,
},
DropNotNull {
drop_not_null_span: Span,
},
}

impl<'a> Spanned for AlterColumnAction<'a> {
fn span(&self) -> Span {
match self {
AlterColumnAction::SetDefault {
set_default_span,
value,
} => set_default_span.join_span(value),
AlterColumnAction::DropDefault { drop_default_span } => drop_default_span.clone(),
AlterColumnAction::Type { type_span, type_ } => type_span.join_span(type_),
AlterColumnAction::SetNotNull { set_not_null_span } => set_not_null_span.clone(),
AlterColumnAction::DropNotNull { drop_not_null_span } => drop_not_null_span.clone(),
}
}
}

/// Enum of alterations to perform on a table
#[derive(Clone, Debug)]
pub enum AlterSpecification<'a> {
Expand Down Expand Up @@ -183,7 +221,7 @@ pub enum AlterSpecification<'a> {
},
/// Modify a column
Modify {
// Span of "MODIFY"
/// Span of "MODIFY"
modify_span: Span,
/// Span of "IF EXISTS" if specified
if_exists: Option<Span>,
Expand All @@ -192,6 +230,21 @@ pub enum AlterSpecification<'a> {
/// New definition of column
definition: DataType<'a>,
},
DropColumn {
/// Span of "DROP COLUMN"
drop_column_span: Span,
/// Name of column to drop
column: Identifier<'a>,
/// Span of "CASCADE" if specified
cascade: Option<Span>,
},
AlterColumn {
/// Span of "ALTER COLUMN"
alter_column_span: Span,
/// Name of column to drop
column: Identifier<'a>,
alter_column_action: AlterColumnAction<'a>,
},
/// Modify a column
OwnerTo {
// Span of "OWNER TO"
Expand Down Expand Up @@ -259,6 +312,18 @@ impl<'a> Spanned for AlterSpecification<'a> {
.join_span(col)
.join_span(definition),
AlterSpecification::OwnerTo { span, owner } => span.join_span(owner),
AlterSpecification::DropColumn {
drop_column_span,
column: col,
cascade,
} => drop_column_span.join_span(col).join_span(cascade),
AlterSpecification::AlterColumn {
alter_column_span,
column: col,
alter_column_action,
} => alter_column_span
.join_span(col)
.join_span(alter_column_action),
}
}
}
Expand Down Expand Up @@ -541,8 +606,8 @@ fn parse_add_alter_specification<'a>(
/// Represent an alter table statement
/// ```
/// # use sql_parse::{SQLDialect, SQLArguments, ParseOptions, parse_statements, AlterTable, Statement, Issues};
/// # let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
/// #
/// let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
///
/// let sql = "ALTER TABLE `t1`
/// MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,
/// ADD CONSTRAINT `t1_t2` FOREIGN KEY (`two`) REFERENCES `t2` (`id`);";
Expand All @@ -557,7 +622,24 @@ fn parse_add_alter_specification<'a>(
/// };
///
/// assert!(alter.table.identifier.as_str() == "t1");
/// println!("{:#?}", alter.alter_specifications)
/// println!("{:#?}", alter.alter_specifications);
///
/// let options = ParseOptions::new().dialect(SQLDialect::PostgreSQL);
/// let sql = "ALTER TABLE t1
/// ALTER COLUMN id DROP NOT NULL,
/// ALTER COLUMN id SET NOT NULL,
/// ALTER COLUMN id SET DEFAULT 47,
/// ALTER COLUMN id DROP DEFAULT,
/// ALTER COLUMN id TYPE int;";
///
/// let mut issues = Issues::new(sql);
/// let mut stmts = parse_statements(sql, &mut issues, &options);
///
/// # assert!(issues.is_ok());
/// let alter: AlterTable = match stmts.pop() {
/// Some(Statement::AlterTable(a)) => a,
/// _ => panic!("We should get an alter table statement")
/// };
///
#[derive(Clone, Debug)]
pub struct AlterTable<'a> {
Expand Down Expand Up @@ -633,6 +715,73 @@ fn parse_alter_table<'a>(
let owner = parser.consume_plain_identifier()?;
AlterSpecification::OwnerTo { span, owner }
}
Token::Ident(_, Keyword::DROP) => {
let drop_column_span =
parser.consume_keywords(&[Keyword::DROP, Keyword::COLUMN])?;
let column = parser.consume_plain_identifier()?;
let cascade = parser.skip_keyword(Keyword::CASCADE);
AlterSpecification::DropColumn {
drop_column_span,
column,
cascade,
}
}
Token::Ident(_, Keyword::ALTER) => {
let span = parser.consume_keywords(&[Keyword::ALTER, Keyword::COLUMN])?;
let column = parser.consume_plain_identifier()?;

let alter_column_action = match parser.token {
Token::Ident(_, Keyword::SET) => {
let set_span = parser.consume();
match parser.token {
Token::Ident(_, Keyword::DEFAULT) => {
let set_default_span = parser.consume().join_span(&set_span);
let value = parse_expression(parser, false)?;
AlterColumnAction::SetDefault {
set_default_span,
value,
}
}
Token::Ident(_, Keyword::NOT) => {
let set_not_null_span = set_span.join_span(
&parser.consume_keywords(&[Keyword::NOT, Keyword::NULL])?,
);
AlterColumnAction::SetNotNull { set_not_null_span }
}
_ => parser.expected_failure("'DEFAULT' or 'NOT NULL'")?,
}
}
Token::Ident(_, Keyword::DROP) => {
let set_span = parser.consume();
match parser.token {
Token::Ident(_, Keyword::DEFAULT) => {
let drop_default_span = parser.consume().join_span(&set_span);
AlterColumnAction::DropDefault {
drop_default_span: drop_default_span,
}
}
Token::Ident(_, Keyword::NOT) => {
let drop_not_null_span = set_span.join_span(
&parser.consume_keywords(&[Keyword::NOT, Keyword::NULL])?,
);
AlterColumnAction::DropNotNull { drop_not_null_span }
}
_ => parser.expected_failure("'DEFAULT' or 'NOT NULL'")?,
}
}
Token::Ident(_, Keyword::TYPE) => {
let type_span = parser.consume();
let type_ = parse_data_type(parser, false)?;
AlterColumnAction::Type { type_span, type_ }
}
_ => parser.expected_failure("alter column action")?,
};
AlterSpecification::AlterColumn {
alter_column_span: span,
column,
alter_column_action,
}
}
_ => parser.expected_failure("alter specification")?,
});
if parser.skip_token(Token::Comma).is_none() {
Expand Down
1 change: 0 additions & 1 deletion src/issue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ impl<'a, 'b> IssueHandle<'a, 'b> {
}
}


#[derive(Debug)]
pub struct Issues<'a> {
pub src: &'a str,
Expand Down
2 changes: 1 addition & 1 deletion src/with_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl<'a> Spanned for WithBlock<'a> {
/// let mut stmts = parse_statements(sql, &mut issues, &options);
///
/// # assert!(issues.is_ok());
/// #
/// #
/// let delete: WithQuery = match stmts.pop() {
/// Some(Statement::WithQuery(d)) => d,
/// _ => panic!("We should get a with statement")
Expand Down
Loading