@@ -211,6 +211,7 @@ class Hive(Dialect):
211211 SAFE_DIVISION = True
212212 ARRAY_AGG_INCLUDES_NULLS = None
213213 REGEXP_EXTRACT_DEFAULT_GROUP = 1
214+ ALTER_TABLE_SUPPORTS_CASCADE = True
214215
215216 # https://spark.apache.org/docs/latest/sql-ref-identifier.html#description
216217 NORMALIZATION_STRATEGY = NormalizationStrategy .CASE_INSENSITIVE
@@ -310,6 +311,10 @@ class Parser(parser.Parser):
310311 VALUES_FOLLOWED_BY_PAREN = False
311312 JOINS_HAVE_EQUAL_PRECEDENCE = True
312313 ADD_JOIN_ON_TRUE = True
314+ ALTER_TABLE_PARTITIONS = True
315+
316+ CHANGE_COLUMN_ALTER_SYNTAX = False
317+ # Whether the dialect supports using ALTER COLUMN syntax with CHANGE COLUMN.
313318
314319 FUNCTIONS = {
315320 ** parser .Parser .FUNCTIONS ,
@@ -378,6 +383,11 @@ class Parser(parser.Parser):
378383 ),
379384 }
380385
386+ ALTER_PARSERS = {
387+ ** parser .Parser .ALTER_PARSERS ,
388+ "CHANGE" : lambda self : self ._parse_alter_table_change (),
389+ }
390+
381391 def _parse_transform (self ) -> t .Optional [exp .Transform | exp .QueryTransform ]:
382392 if not self ._match (TokenType .L_PAREN , advance = False ):
383393 self ._retreat (self ._index - 1 )
@@ -451,6 +461,35 @@ def _parse_types(
451461
452462 return this
453463
464+ def _parse_alter_table_change (self ) -> t .Optional [exp .Expression ]:
465+ self ._match (TokenType .COLUMN )
466+ this = self ._parse_field (any_token = True )
467+
468+ if self .CHANGE_COLUMN_ALTER_SYNTAX and self ._match_text_seq ("TYPE" ):
469+ return self .expression (
470+ exp .AlterColumn ,
471+ this = this ,
472+ dtype = self ._parse_types (schema = True ),
473+ )
474+
475+ column_new = self ._parse_field (any_token = True )
476+ dtype = self ._parse_types (schema = True )
477+
478+ comment = self ._match (TokenType .COMMENT ) and self ._parse_string ()
479+
480+ if not this or not column_new or not dtype :
481+ self .raise_error (
482+ "Expected 'CHANGE COLUMN' to be followed by 'column_name' 'column_name' 'data_type'"
483+ )
484+
485+ return self .expression (
486+ exp .AlterColumn ,
487+ this = this ,
488+ rename_to = column_new ,
489+ dtype = dtype ,
490+ comment = comment ,
491+ )
492+
454493 def _parse_partition_and_order (
455494 self ,
456495 ) -> t .Tuple [t .List [exp .Expression ], t .Optional [exp .Expression ]]:
@@ -500,6 +539,7 @@ class Generator(generator.Generator):
500539 PAD_FILL_PATTERN_IS_REQUIRED = True
501540 SUPPORTS_MEDIAN = False
502541 ARRAY_SIZE_NAME = "SIZE"
542+ ALTER_SET_TYPE = ""
503543
504544 EXPRESSIONS_WITHOUT_NESTED_CTES = {
505545 exp .Insert ,
@@ -757,6 +797,32 @@ def columndef_sql(self, expression: exp.ColumnDef, sep: str = " ") -> str:
757797 ),
758798 )
759799
800+ def altercolumn_sql (self , expression : exp .AlterColumn ) -> str :
801+ this = self .sql (expression , "this" )
802+ new_name = self .sql (expression , "rename_to" ) or this
803+ dtype = self .sql (expression , "dtype" )
804+ comment = (
805+ f" COMMENT { self .sql (expression , 'comment' )} "
806+ if self .sql (expression , "comment" )
807+ else ""
808+ )
809+ default = self .sql (expression , "default" )
810+ visible = expression .args .get ("visible" )
811+ allow_null = expression .args .get ("allow_null" )
812+ drop = expression .args .get ("drop" )
813+
814+ if any ([default , drop , visible , allow_null , drop ]):
815+ self .unsupported ("Unsupported CHANGE COLUMN syntax" )
816+
817+ if not dtype :
818+ self .unsupported ("CHANGE COLUMN without a type is not supported" )
819+
820+ return f"CHANGE COLUMN { this } { new_name } { dtype } { comment } "
821+
822+ def renamecolumn_sql (self , expression : exp .RenameColumn ) -> str :
823+ self .unsupported ("Cannot rename columns without data type defined in Hive" )
824+ return ""
825+
760826 def alterset_sql (self , expression : exp .AlterSet ) -> str :
761827 exprs = self .expressions (expression , flat = True )
762828 exprs = f" { exprs } " if exprs else ""
0 commit comments