Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ statement
(RESTRICT | CASCADE)? #dropNamespace
| SHOW namespaces ((FROM | IN) multipartIdentifier)?
(LIKE? pattern=STRING)? #showNamespaces
| createTableHeader ('(' colTypeList ')')? tableProvider?
| createTableHeader ('(' createTableColTypeList ')')? tableProvider?
Comment thread
dtenedor marked this conversation as resolved.
Outdated
createTableClauses
(AS? query)? #createTable
| CREATE TABLE (IF NOT EXISTS)? target=tableIdentifier
Expand Down Expand Up @@ -961,7 +961,11 @@ qualifiedColTypeWithPositionList
;

qualifiedColTypeWithPosition
: name=multipartIdentifier dataType (NOT NULL)? commentSpec? colPosition?
: name=multipartIdentifier dataType (NOT NULL)? defaultExpression? commentSpec? colPosition?
;

defaultExpression
: DEFAULT expression
;

colTypeList
Expand All @@ -972,6 +976,14 @@ colType
: colName=errorCapturingIdentifier dataType (NOT NULL)? commentSpec?
;

createTableColTypeList
: createTableColType (',' createTableColType)*
;

createTableColType
: colName=errorCapturingIdentifier dataType (NOT NULL)? defaultExpression? commentSpec?
;

complexColTypeList
: complexColType (',' complexColType)*
;
Expand Down Expand Up @@ -1078,6 +1090,8 @@ alterColumnAction
| commentSpec
| colPosition
| setOrDrop=(SET | DROP) NOT NULL
| SET defaultExpression
Comment thread
dtenedor marked this conversation as resolved.
| dropDefault=DROP DEFAULT
Comment thread
dtenedor marked this conversation as resolved.
;


Expand Down Expand Up @@ -1132,6 +1146,7 @@ ansiNonReserved
| DATABASES
| DAY
| DBPROPERTIES
| DEFAULT
| DEFINED
| DELETE
| DELIMITED
Expand Down Expand Up @@ -1379,6 +1394,7 @@ nonReserved
| DATABASES
| DAY
| DBPROPERTIES
| DEFAULT
| DEFINED
| DELETE
| DELIMITED
Expand Down Expand Up @@ -1645,6 +1661,7 @@ DATA: 'DATA';
DATABASE: 'DATABASE';
DATABASES: 'DATABASES';
DBPROPERTIES: 'DBPROPERTIES';
DEFAULT: 'DEFAULT';
DEFINED: 'DEFINED';
DELETE: 'DELETE';
DELIMITED: 'DELIMITED';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2756,6 +2756,41 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
metadata = builder.build())
}

/**
* Create a [[StructType]] from a number of CREATE TABLE column definitions.
*/
override def visitCreateTableColTypeList(
ctx: CreateTableColTypeListContext): Seq[StructField] = withOrigin(ctx) {
ctx.createTableColType().asScala.map(visitCreateTableColType).toSeq
}

/**
* Create a top level [[StructField]] from a CREATE TABLE column definition.
*/
override def visitCreateTableColType(
ctx: CreateTableColTypeContext): StructField = withOrigin(ctx) {
import ctx._

val builder = new MetadataBuilder
// Add comment to metadata
Option(commentSpec()).map(visitCommentSpec).foreach {
builder.putString("comment", _)
}

// Process the 'DEFAULT expression' clause in the column definition, if any.
val name: String = colName.getText
val defaultExpr = Option(ctx.defaultExpression()).map(visitDefaultExpression)
if (defaultExpr != None) {
Comment thread
dtenedor marked this conversation as resolved.
Outdated
throw new ParseException(defaultColumnNotImplementedYetError, ctx)
Comment thread
dtenedor marked this conversation as resolved.
Outdated
}

StructField(
name = name,
dataType = typedVisit[DataType](ctx.dataType),
nullable = NULL == null,
metadata = builder.build())
}

/**
* Create a [[StructType]] from a sequence of [[StructField]]s.
*/
Expand Down Expand Up @@ -3459,7 +3494,8 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
override def visitCreateTable(ctx: CreateTableContext): LogicalPlan = withOrigin(ctx) {
Comment thread
dtenedor marked this conversation as resolved.
val (table, temp, ifNotExists, external) = visitCreateTableHeader(ctx.createTableHeader)

val columns = Option(ctx.colTypeList()).map(visitColTypeList).getOrElse(Nil)
val columns = Option(ctx.createTableColTypeList()).map(visitCreateTableColTypeList)
.getOrElse(Nil)
val provider = Option(ctx.tableProvider).map(_.multipartIdentifier.getText)
val (partTransforms, partCols, bucketSpec, properties, options, location, comment, serdeInfo) =
visitCreateTableClauses(ctx.createTableClauses())
Expand Down Expand Up @@ -3651,12 +3687,20 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
}
}

private def defaultColumnNotImplementedYetError = {
"Support for DEFAULT column values is not implemented yet"
}

/**
* Parse new column info from ADD COLUMN into a QualifiedColType.
*/
override def visitQualifiedColTypeWithPosition(
ctx: QualifiedColTypeWithPositionContext): QualifiedColType = withOrigin(ctx) {
val name = typedVisit[Seq[String]](ctx.name)
val defaultExpr = Option(ctx.defaultExpression()).map(visitDefaultExpression)
if (defaultExpr != None) {
Comment thread
dtenedor marked this conversation as resolved.
Outdated
throw new ParseException(defaultColumnNotImplementedYetError, ctx)
}
QualifiedColType(
path = if (name.length > 1) Some(UnresolvedFieldName(name.init)) else None,
colName = name.last,
Expand Down Expand Up @@ -3745,6 +3789,12 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
} else {
None
}
if (action.defaultExpression != null) {
throw new ParseException(defaultColumnNotImplementedYetError, ctx)
}
if (action.dropDefault != null) {
throw new ParseException(defaultColumnNotImplementedYetError, ctx)
}

assert(Seq(dataType, nullable, comment, position).count(_.nonEmpty) == 1)

Expand Down Expand Up @@ -3813,6 +3863,9 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
throw QueryParsingErrors.operationInHiveStyleCommandUnsupportedError(
"Replacing with a nested column", "REPLACE COLUMNS", ctx)
}
if (Option(colType.defaultExpression()).map(visitDefaultExpression) != None) {
Comment thread
dtenedor marked this conversation as resolved.
Outdated
throw new ParseException(defaultColumnNotImplementedYetError, ctx)
}
col
}.toSeq
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2235,4 +2235,44 @@ class DDLParserSuite extends AnalysisTest {
comparePlans(parsePlan(timestampTypeSql), insertPartitionPlan(timestamp))
comparePlans(parsePlan(binaryTypeSql), insertPartitionPlan(binaryStr))
}

test("SPARK-38334: Implement support for DEFAULT values for columns in tables") {
// The following commands will support DEFAULT columns, but this has not been implemented yet.
for (sql <- Seq(
"ALTER TABLE t1 ADD COLUMN x int NOT NULL DEFAULT 42",
"ALTER TABLE t1 ALTER COLUMN a.b.c SET DEFAULT 42",
"ALTER TABLE t1 ALTER COLUMN a.b.c DROP DEFAULT",
"ALTER TABLE t1 REPLACE COLUMNS (x STRING DEFAULT 42)",
"CREATE TABLE my_tab(a INT COMMENT 'test', b STRING NOT NULL DEFAULT \"abc\") USING parquet"
)) {
val exc = intercept[ParseException] {
parsePlan(sql);
}
assert(exc.getMessage.contains("Support for DEFAULT column values is not implemented yet"));
}
// In each of the following cases, the DEFAULT reference parses as an unresolved attribute
// reference. We can handle these cases after the parsing stage, at later phases of analysis.
for (sql <- Seq(
"VALUES (1, 2, DEFAULT)",
"INSERT INTO t PARTITION(part = date'2019-01-02') VALUES ('a', DEFAULT)",
"""
|MERGE INTO testcat1.ns1.ns2.tbl AS target
|USING testcat2.ns1.ns2.tbl AS source
|ON target.col1 = source.col1
|WHEN MATCHED AND (target.col2='delete') THEN DELETE
|WHEN MATCHED AND (target.col2='update') THEN UPDATE SET target.col2 = source.col2
|WHEN NOT MATCHED AND (target.col2='insert')
|THEN INSERT (target.col1, target.col2) values (source.col1, DEFAULT)
""".stripMargin
)) {
assert(!parsePlan(sql).resolved)
}
// REPLACE TABLE does not support DEFAULT columns, and here we check that the parser rejects
// naturally.
var exc = intercept[ParseException] {
parsePlan("REPLACE TABLE my_tab(a INT COMMENT 'test', b STRING NOT NULL " +
" DEFAULT \"xyz\") USING parquet")
}
assert(exc.getMessage.contains("mismatched input 'DEFAULT'"))
}
}