Skip to content
Closed
2 changes: 2 additions & 0 deletions docs/sql-migration-guide-upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ displayTitle: Spark SQL Upgrading Guide

- In Spark version 2.4 and earlier, float/double -0.0 is semantically equal to 0.0, but users can still distinguish them via `Dataset.show`, `Dataset.collect` etc. Since Spark 3.0, float/double -0.0 is replaced by 0.0 internally, and users can't distinguish them any more.

- In Spark version 2.4 and earlier, the `SET` command works without any warnings even if the specified key is for `SparkConf` entries and it has no effect because the command does not update `SparkConf`, but the behavior might confuse users. Since 3.0, the command fails if a non-SQL or static SQL config key is used. You can disable such a check by setting `spark.sql.execution.setCommandRejectsSparkConfs` to `false`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I looked at that code again, the static config part already threw an error before, so probably can be removed here.


## Upgrading From Spark SQL 2.3 to 2.4

- In Spark version 2.3 and earlier, the second parameter to array_contains function is implicitly promoted to the element type of first array type parameter. This type promotion can be lossy and may cause `array_contains` function to return wrong result. This problem has been addressed in 2.4 by employing a safer type promotion mechanism. This can cause some change in behavior and are illustrated in the table below.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import org.apache.spark.util.Utils

object SQLConf {

private val sqlConfEntries = java.util.Collections.synchronizedMap(
private[sql] val sqlConfEntries = java.util.Collections.synchronizedMap(
new java.util.HashMap[String, ConfigEntry[_]]())

val staticConfKeys: java.util.Set[String] =
Expand Down Expand Up @@ -1610,6 +1610,14 @@ object SQLConf {
""" "... N more fields" placeholder.""")
.intConf
.createWithDefault(25)

val SET_COMMAND_REJECTS_SPARK_CONFS =
buildConf("spark.sql.execution.setCommandRejectsSparkConfs")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we use the legacy prefix?

.internal()
.doc("If it is set to true, SET command will fail when the key is registered as " +
"an SparkConf entry.")
.booleanConf
.createWithDefault(true)
}

/**
Expand Down Expand Up @@ -2030,6 +2038,8 @@ class SQLConf extends Serializable with Logging {

def maxToStringFields: Int = getConf(SQLConf.MAX_TO_STRING_FIELDS)

def setCommandRejectsSparkConfs: Boolean = getConf(SQLConf.SET_COMMAND_REJECTS_SPARK_CONFS)

/** ********************** SQLConf functionality methods ************ */

/** Set Spark SQL configuration properties. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,9 @@ class RuntimeConfig private[sql](sqlConf: SQLConf = new SQLConf) {
if (SQLConf.staticConfKeys.contains(key)) {
throw new AnalysisException(s"Cannot modify the value of a static config: $key")
}
if (sqlConf.setCommandRejectsSparkConfs &&
ConfigEntry.findEntry(key) != null && !SQLConf.sqlConfEntries.containsKey(key)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, thinking of it, isn't ConfigEntry.findEntry(key) != null redundant with the other check?

Removing that would also want by other settings that don't have constants defined.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry for the delay.
As per the comment #22887 (comment), I'd leave it as is for now.

@cloud-fan cloud-fan Nov 28, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should only reject configs that are registered as SparkConf. Thinking about configs that are neither a SparkConf or SQLConf, we shouldn't reject it.

throw new AnalysisException(s"Cannot modify the value of a Spark config: $key")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,13 @@ class RuntimeConfigSuite extends SparkFunSuite {
assert(!conf.isModifiable(""))
assert(!conf.isModifiable("invalid config parameter"))
}

test("reject SparkConf entries") {
val conf = newConf()

val ex = intercept[AnalysisException] {
conf.set("spark.task.cpus", 4)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use config.CPUS_PER_TASK instead of hardcoding it?

}
assert(ex.getMessage.contains("Spark config"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2715,4 +2715,11 @@ abstract class DDLSuite extends QueryTest with SQLTestUtils {
}
}
}

test("set command rejects SparkConf entries") {
val ex = intercept[AnalysisException] {
sql("SET spark.task.cpus = 4")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

}
assert(ex.getMessage.contains("Spark config"))
}
}