Skip to content

Commit 14eadf9

Browse files
committed
[SPARK-11352][SQL] Escape */ in the generated comments.
https://issues.apache.org/jira/browse/SPARK-11352 Author: Yin Huai <yhuai@databricks.com> Closes apache#10072 from yhuai/SPARK-11352. (cherry picked from commit 5872a9d) Signed-off-by: Yin Huai <yhuai@databricks.com>
1 parent 1135430 commit 14eadf9

File tree

3 files changed

+18
-3
lines changed

3 files changed

+18
-3
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Expression.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,15 @@ abstract class Expression extends TreeNode[Expression] {
9595
ctx.subExprEliminationExprs.get(this).map { subExprState =>
9696
// This expression is repeated meaning the code to evaluated has already been added
9797
// as a function and called in advance. Just use it.
98-
val code = s"/* $this */"
98+
val code = s"/* ${this.toCommentSafeString} */"
9999
GeneratedExpressionCode(code, subExprState.isNull, subExprState.value)
100100
}.getOrElse {
101101
val isNull = ctx.freshName("isNull")
102102
val primitive = ctx.freshName("primitive")
103103
val ve = GeneratedExpressionCode("", isNull, primitive)
104104
ve.code = genCode(ctx, ve)
105105
// Add `this` in the comment.
106-
ve.copy(s"/* $this */\n" + ve.code.trim)
106+
ve.copy(s"/* ${this.toCommentSafeString} */\n" + ve.code.trim)
107107
}
108108
}
109109

@@ -214,6 +214,12 @@ abstract class Expression extends TreeNode[Expression] {
214214
}
215215

216216
override def toString: String = prettyName + flatArguments.mkString("(", ",", ")")
217+
218+
/**
219+
* Returns the string representation of this expression that is safe to be put in
220+
* code comments of generated code.
221+
*/
222+
protected def toCommentSafeString: String = this.toString.replace("*/", "\\*\\/")
217223
}
218224

219225

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/CodegenFallback.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ trait CodegenFallback extends Expression {
3333
ctx.references += this
3434
val objectTerm = ctx.freshName("obj")
3535
s"""
36-
/* expression: ${this} */
36+
/* expression: ${this.toCommentSafeString} */
3737
java.lang.Object $objectTerm = expressions[${ctx.references.size - 1}].eval(${ctx.INPUT_ROW});
3838
boolean ${ev.isNull} = $objectTerm == null;
3939
${ctx.javaType(this.dataType)} ${ev.value} = ${ctx.defaultValue(this.dataType)};

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CodeGenerationSuite.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,13 @@ class CodeGenerationSuite extends SparkFunSuite with ExpressionEvalHelper {
9898
unsafeRow.getStruct(3, 1).getStruct(0, 2).setInt(1, 4)
9999
assert(internalRow === internalRow2)
100100
}
101+
102+
test("*/ in the data") {
103+
// When */ appears in a comment block (i.e. in /**/), code gen will break.
104+
// So, in Expression and CodegenFallback, we escape */ to \*\/.
105+
checkEvaluation(
106+
EqualTo(BoundReference(0, StringType, false), Literal.create("*/", StringType)),
107+
true,
108+
InternalRow(UTF8String.fromString("*/")))
109+
}
101110
}

0 commit comments

Comments
 (0)