From 596c2804265e457c378cec433ba2b7fe64f4efdd Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Sat, 12 Aug 2017 16:37:04 +0800 Subject: [PATCH 01/11] fix null field name and add corresponding test --- .../spark/sql/catalyst/expressions/jsonExpressions.scala | 8 +++++++- .../spark/sql/execution/datasources/json/JsonSuite.scala | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala index 6f451fe54761..4b29cad79954 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala @@ -362,9 +362,15 @@ case class JsonTuple(children: Seq[Expression]) @transient private lazy val fieldExpressions: Seq[Expression] = children.tail // eagerly evaluate any foldable the field names + private val nullFieldName = "__NullFieldName" @transient private lazy val foldableFieldNames: IndexedSeq[String] = { fieldExpressions.map { - case expr if expr.foldable => expr.eval().asInstanceOf[UTF8String].toString + case expr if expr.foldable => + if (expr.eval() == null) { + nullFieldName + } else { + expr.eval().asInstanceOf[UTF8String].toString + } case _ => null }.toIndexedSeq } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala index 80e5dd161d1f..61152fdc7a22 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala @@ -2034,4 +2034,13 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData { } } } + + test("SPARK-21677: json_tuple throws NullPointException when column is null as string type") { + checkAnswer(sql( + """ + |SELECT json_tuple('{"a" : 1, "b" : 2}' + |, cast(NULL AS STRING), 'b' + |, cast(NULL AS STRING), 'a') + """.stripMargin), Row(null, "2", null, "1")) + } } From 796041f0f84eac70a2528c37e02dbe4163ddf3aa Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Sat, 12 Aug 2017 16:39:56 +0800 Subject: [PATCH 02/11] add description --- .../spark/sql/catalyst/expressions/jsonExpressions.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala index 4b29cad79954..3e6366809d01 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala @@ -361,8 +361,10 @@ case class JsonTuple(children: Seq[Expression]) // the fields to query are the remaining children @transient private lazy val fieldExpressions: Seq[Expression] = children.tail - // eagerly evaluate any foldable the field names + // e.g., trim(null) will raise NPE in asInstanceOf[UTF8String].toString private val nullFieldName = "__NullFieldName" + + // eagerly evaluate any foldable the field names @transient private lazy val foldableFieldNames: IndexedSeq[String] = { fieldExpressions.map { case expr if expr.foldable => From f07a9f7e73a17ab5447945d8139a40a1ba8372c5 Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Sun, 13 Aug 2017 09:48:31 +0800 Subject: [PATCH 03/11] modify the comment about nullFieldName --- .../apache/spark/sql/catalyst/expressions/jsonExpressions.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala index 3e6366809d01..0a724a0792b8 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala @@ -361,7 +361,7 @@ case class JsonTuple(children: Seq[Expression]) // the fields to query are the remaining children @transient private lazy val fieldExpressions: Seq[Expression] = children.tail - // e.g., trim(null) will raise NPE in asInstanceOf[UTF8String].toString + // toString on null will throw NullPointerException so that return a very unlikely column name private val nullFieldName = "__NullFieldName" // eagerly evaluate any foldable the field names From ffa575a6731fef3e0731b73e0f7311cb024e831b Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Sun, 13 Aug 2017 10:48:19 +0800 Subject: [PATCH 04/11] make properly comment on pseudo field name --- .../apache/spark/sql/catalyst/expressions/jsonExpressions.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala index 0a724a0792b8..b69b5d1f0424 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala @@ -361,7 +361,7 @@ case class JsonTuple(children: Seq[Expression]) // the fields to query are the remaining children @transient private lazy val fieldExpressions: Seq[Expression] = children.tail - // toString on null will throw NullPointerException so that return a very unlikely column name + // a field name given with constant null will be replaced with this pseudo field name private val nullFieldName = "__NullFieldName" // eagerly evaluate any foldable the field names From 5d712637ba0710d9edda79c2097b4044adca75e0 Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Mon, 14 Aug 2017 23:17:20 +0800 Subject: [PATCH 05/11] discard fake field name, apply Option instead --- .../expressions/jsonExpressions.scala | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala index b69b5d1f0424..4c657b589d96 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala @@ -359,22 +359,14 @@ case class JsonTuple(children: Seq[Expression]) @transient private lazy val jsonExpr: Expression = children.head // the fields to query are the remaining children - @transient private lazy val fieldExpressions: Seq[Expression] = children.tail - - // a field name given with constant null will be replaced with this pseudo field name - private val nullFieldName = "__NullFieldName" + @transient private lazy val fieldExpressions: Array[Expression] = children.tail.toArray // eagerly evaluate any foldable the field names - @transient private lazy val foldableFieldNames: IndexedSeq[String] = { + @transient private lazy val foldableFieldNames: Array[Option[String]] = { fieldExpressions.map { - case expr if expr.foldable => - if (expr.eval() == null) { - nullFieldName - } else { - expr.eval().asInstanceOf[UTF8String].toString - } + case expr if expr.foldable => Option(expr.eval()).map(_.asInstanceOf[UTF8String].toString) case _ => null - }.toIndexedSeq + } } // and count the number of foldable fields, we'll use this later to optimize evaluation @@ -425,7 +417,7 @@ case class JsonTuple(children: Seq[Expression]) val fieldNames = if (constantFields == fieldExpressions.length) { // typically the user will provide the field names as foldable expressions // so we can use the cached copy - foldableFieldNames + foldableFieldNames.map(_.orNull) } else if (constantFields == 0) { // none are foldable so all field names need to be evaluated from the input row fieldExpressions.map(_.eval(input).asInstanceOf[UTF8String].toString) @@ -434,7 +426,7 @@ case class JsonTuple(children: Seq[Expression]) // prefer the cached copy when available foldableFieldNames.zip(fieldExpressions).map { case (null, expr) => expr.eval(input).asInstanceOf[UTF8String].toString - case (fieldName, _) => fieldName + case (fieldName, _) => fieldName.orNull } } From 0078445575064a3eec455bcec62fbed0c6dd2001 Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Tue, 15 Aug 2017 12:48:06 +0800 Subject: [PATCH 06/11] added unit test that mixes constant field name and non constant one field name --- .../sql/execution/datasources/json/JsonSuite.scala | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala index 61152fdc7a22..f70141de516f 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala @@ -2042,5 +2042,17 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData { |, cast(NULL AS STRING), 'b' |, cast(NULL AS STRING), 'a') """.stripMargin), Row(null, "2", null, "1")) + + // mixes constant field name and non constant one + withTempView("jsonTable") { + Seq(("""{"a": 1, "b": 2}""", "a", "b")) + .toDF("jsonField", "a", "b") + .createOrReplaceTempView("jsonTable") + + checkAnswer( + sql("""SELECT json_tuple(jsonField, b, cast(NULL AS STRING), 'a') FROM jsonTable"""), + Row("2", null, "1") + ) + } } } From 5c69df524ea4a037095005ad9915cac4ca4aedc5 Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Tue, 15 Aug 2017 15:55:58 +0800 Subject: [PATCH 07/11] use IndexedSeq instead of Array on foldableFieldNames to get better performance --- .../spark/sql/catalyst/expressions/jsonExpressions.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala index 4c657b589d96..21a04677e2c8 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala @@ -359,15 +359,15 @@ case class JsonTuple(children: Seq[Expression]) @transient private lazy val jsonExpr: Expression = children.head // the fields to query are the remaining children - @transient private lazy val fieldExpressions: Array[Expression] = children.tail.toArray + @transient private lazy val fieldExpressions: Seq[Expression] = children.tail // eagerly evaluate any foldable the field names - @transient private lazy val foldableFieldNames: Array[Option[String]] = { + @transient private lazy val foldableFieldNames: IndexedSeq[Option[String]] = { fieldExpressions.map { case expr if expr.foldable => Option(expr.eval()).map(_.asInstanceOf[UTF8String].toString) case _ => null } - } + }.toIndexedSeq // and count the number of foldable fields, we'll use this later to optimize evaluation @transient private lazy val constantFields: Int = foldableFieldNames.count(_ != null) @@ -430,6 +430,7 @@ case class JsonTuple(children: Seq[Expression]) } } + // Array[String] val row = Array.ofDim[Any](fieldNames.length) // start reading through the token stream, looking for any requested field names From ab16929f4b5fe40e9807f2678f6e55260e1922f2 Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Tue, 15 Aug 2017 22:13:51 +0800 Subject: [PATCH 08/11] remove redundant comment and move toIndexedSeq after the map --- .../spark/sql/catalyst/expressions/jsonExpressions.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala index 21a04677e2c8..0eef0001fe38 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/jsonExpressions.scala @@ -366,8 +366,8 @@ case class JsonTuple(children: Seq[Expression]) fieldExpressions.map { case expr if expr.foldable => Option(expr.eval()).map(_.asInstanceOf[UTF8String].toString) case _ => null - } - }.toIndexedSeq + }.toIndexedSeq + } // and count the number of foldable fields, we'll use this later to optimize evaluation @transient private lazy val constantFields: Int = foldableFieldNames.count(_ != null) @@ -430,7 +430,6 @@ case class JsonTuple(children: Seq[Expression]) } } - // Array[String] val row = Array.ofDim[Any](fieldNames.length) // start reading through the token stream, looking for any requested field names From e0e0c7423c31aba665290a8323bd8b38e2cb8486 Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Wed, 16 Aug 2017 23:09:50 +0800 Subject: [PATCH 09/11] move test case from JsonSuite to JsonExpressionsSuite and add new test case in json-functions.sql --- .../expressions/JsonExpressionsSuite.scala | 10 +++++++++ .../sql-tests/inputs/json-functions.sql | 6 ++++++ .../datasources/json/JsonSuite.scala | 21 ------------------- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/JsonExpressionsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/JsonExpressionsSuite.scala index f892e8020460..1cd2b4fc18a5 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/JsonExpressionsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/JsonExpressionsSuite.scala @@ -363,6 +363,16 @@ class JsonExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper { InternalRow(UTF8String.fromString("b\nc"))) } + test("SPARK-21677: json_tuple throws NullPointException when column is null as string type") { + checkJsonTuple( + JsonTuple(Literal("""{"f1": 1, "f2": 2}""") :: + NonFoldableLiteral("f1") :: + NonFoldableLiteral("cast(NULL AS STRING)") :: + NonFoldableLiteral("f2") :: + Nil), + InternalRow(UTF8String.fromString("1"), null, UTF8String.fromString("2"))) + } + val gmtId = Option(DateTimeUtils.TimeZoneGMT.getID) test("from_json") { diff --git a/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql b/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql index b3cc2cea51d4..d8ddad7f90ab 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql @@ -20,3 +20,9 @@ select from_json('{"a":1}', 'a InvalidType'); select from_json('{"a":1}', 'a INT', named_struct('mode', 'PERMISSIVE')); select from_json('{"a":1}', 'a INT', map('mode', 1)); select from_json(); +-- json_tuple +describe function json_tuple; +describe function extended json_tuple; +select json_tuple('{"a" : 1, "b" : 2}', cast(NULL AS STRING), 'b', cast(NULL AS STRING), 'a') +create temporary view jsonTable(jsonField, a, b) as select * from values '{"a": 1, "b": 2}', 'a', 'b'; +SELECT json_tuple(jsonField, b, cast(NULL AS STRING), 'a') FROM jsonTable \ No newline at end of file diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala index f70141de516f..80e5dd161d1f 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/json/JsonSuite.scala @@ -2034,25 +2034,4 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData { } } } - - test("SPARK-21677: json_tuple throws NullPointException when column is null as string type") { - checkAnswer(sql( - """ - |SELECT json_tuple('{"a" : 1, "b" : 2}' - |, cast(NULL AS STRING), 'b' - |, cast(NULL AS STRING), 'a') - """.stripMargin), Row(null, "2", null, "1")) - - // mixes constant field name and non constant one - withTempView("jsonTable") { - Seq(("""{"a": 1, "b": 2}""", "a", "b")) - .toDF("jsonField", "a", "b") - .createOrReplaceTempView("jsonTable") - - checkAnswer( - sql("""SELECT json_tuple(jsonField, b, cast(NULL AS STRING), 'a') FROM jsonTable"""), - Row("2", null, "1") - ) - } - } } From 5191ed48a57017b3eeb3336e7ffa4a823dca5c28 Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Thu, 17 Aug 2017 10:48:18 +0800 Subject: [PATCH 10/11] consistent style in SQL and append the corresponding golden file of json-functions.sql --- .../sql-tests/inputs/json-functions.sql | 10 +++--- .../sql-tests/results/json-functions.sql.out | 34 ++++++++++++++++++- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql b/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql index d8ddad7f90ab..38a6b950f7fb 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql @@ -21,8 +21,8 @@ select from_json('{"a":1}', 'a INT', named_struct('mode', 'PERMISSIVE')); select from_json('{"a":1}', 'a INT', map('mode', 1)); select from_json(); -- json_tuple -describe function json_tuple; -describe function extended json_tuple; -select json_tuple('{"a" : 1, "b" : 2}', cast(NULL AS STRING), 'b', cast(NULL AS STRING), 'a') -create temporary view jsonTable(jsonField, a, b) as select * from values '{"a": 1, "b": 2}', 'a', 'b'; -SELECT json_tuple(jsonField, b, cast(NULL AS STRING), 'a') FROM jsonTable \ No newline at end of file +SELECT json_tuple('{"a" : 1, "b" : 2}', CAST(NULL AS STRING), 'b', CAST(NULL AS STRING), 'a'); +CREATE TEMPORARY VIEW jsonTable(jsonField, a, b) AS SELECT * FROM VALUES ('{"a": 1, "b": 2}', 'a', 'b'); +SELECT json_tuple(jsonField, b, CAST(NULL AS STRING), 'a') FROM jsonTable; +-- Clean up +DROP VIEW IF EXISTS jsonTable; \ No newline at end of file diff --git a/sql/core/src/test/resources/sql-tests/results/json-functions.sql.out b/sql/core/src/test/resources/sql-tests/results/json-functions.sql.out index 22da20d9a9f4..6983e4a5a2cf 100644 --- a/sql/core/src/test/resources/sql-tests/results/json-functions.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/json-functions.sql.out @@ -1,5 +1,5 @@ -- Automatically generated by SQLQueryTestSuite --- Number of queries: 17 +-- Number of queries: 21 -- !query 0 @@ -178,3 +178,35 @@ struct<> -- !query 16 output org.apache.spark.sql.AnalysisException Invalid number of arguments for function from_json; line 1 pos 7 + + +-- !query 17 +SELECT json_tuple('{"a" : 1, "b" : 2}', CAST(NULL AS STRING), 'b', CAST(NULL AS STRING), 'a') +-- !query 17 schema +struct +-- !query 17 output +NULL 2 NULL 1 + + +-- !query 18 +CREATE TEMPORARY VIEW jsonTable(jsonField, a, b) AS SELECT * FROM VALUES ('{"a": 1, "b": 2}', 'a', 'b') +-- !query 18 schema +struct<> +-- !query 18 output + + + +-- !query 19 +SELECT json_tuple(jsonField, b, CAST(NULL AS STRING), 'a') FROM jsonTable +-- !query 19 schema +struct +-- !query 19 output +2 NULL 1 + + +-- !query 20 +DROP VIEW IF EXISTS jsonTable +-- !query 20 schema +struct<> +-- !query 20 output + From ff3b9daa0cb7d271872af914f5c5a6223f3c855c Mon Sep 17 00:00:00 2001 From: Jen-Ming Chung Date: Thu, 17 Aug 2017 22:06:19 +0800 Subject: [PATCH 11/11] add a newline at the end and alter SQL --- .../src/test/resources/sql-tests/inputs/json-functions.sql | 6 +++--- .../test/resources/sql-tests/results/json-functions.sql.out | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql b/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql index 38a6b950f7fb..5a46fb4321f9 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/json-functions.sql @@ -22,7 +22,7 @@ select from_json('{"a":1}', 'a INT', map('mode', 1)); select from_json(); -- json_tuple SELECT json_tuple('{"a" : 1, "b" : 2}', CAST(NULL AS STRING), 'b', CAST(NULL AS STRING), 'a'); -CREATE TEMPORARY VIEW jsonTable(jsonField, a, b) AS SELECT * FROM VALUES ('{"a": 1, "b": 2}', 'a', 'b'); -SELECT json_tuple(jsonField, b, CAST(NULL AS STRING), 'a') FROM jsonTable; +CREATE TEMPORARY VIEW jsonTable(jsonField, a) AS SELECT * FROM VALUES ('{"a": 1, "b": 2}', 'a'); +SELECT json_tuple(jsonField, 'b', CAST(NULL AS STRING), a) FROM jsonTable; -- Clean up -DROP VIEW IF EXISTS jsonTable; \ No newline at end of file +DROP VIEW IF EXISTS jsonTable; diff --git a/sql/core/src/test/resources/sql-tests/results/json-functions.sql.out b/sql/core/src/test/resources/sql-tests/results/json-functions.sql.out index 6983e4a5a2cf..ae21d00116e9 100644 --- a/sql/core/src/test/resources/sql-tests/results/json-functions.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/json-functions.sql.out @@ -189,7 +189,7 @@ NULL 2 NULL 1 -- !query 18 -CREATE TEMPORARY VIEW jsonTable(jsonField, a, b) AS SELECT * FROM VALUES ('{"a": 1, "b": 2}', 'a', 'b') +CREATE TEMPORARY VIEW jsonTable(jsonField, a) AS SELECT * FROM VALUES ('{"a": 1, "b": 2}', 'a') -- !query 18 schema struct<> -- !query 18 output @@ -197,7 +197,7 @@ struct<> -- !query 19 -SELECT json_tuple(jsonField, b, CAST(NULL AS STRING), 'a') FROM jsonTable +SELECT json_tuple(jsonField, 'b', CAST(NULL AS STRING), a) FROM jsonTable -- !query 19 schema struct -- !query 19 output