Почему SparkSQL требует двух буквальных обратных косых черт в SQL-запросе?

Когда я запускаю приведенный ниже код Scala из Spark 2.0 REPL (spark-shell), он работает, как я и предполагал, разбивая строку с помощью простого регулярного выражения.

import org.apache.spark.sql.SparkSession

// Create session
val sparkSession = SparkSession.builder.master("local").getOrCreate()

// Use SparkSQL to split a string
val query = "SELECT split('What is this? A string I think', '\\\\?') AS result"
println("The query is: " + query)
val dataframe = sparkSession.sql(query)

// Show the result
dataframe.show(1, false)

давая ожидаемый результат

+---------------------------------+
|result                           |
+---------------------------------+
|[What is this,  A string I think]|
+---------------------------------+

Но меня смущает необходимость экранировать буквальный вопросительный знак не одинарной, а двойной обратной косой чертой (здесь представлены четыре обратные косые черты, поскольку мы, конечно, должны избежать обратной косой черты в Scala, если не используем тройные кавычки).

Я подтвердил, что очень похожий код, написанный моим коллегой для Spark 1.5, отлично работает с использованием одной (буквальной) обратной косой черты. Но если я использую только одну буквальную обратную косую черту в Spark 2.1, я получаю ошибку от механизма регулярных выражений JVM, "Dangling meta character '?' near index 0". Я знаю, что это означает, что вопросительный знак не был экранирован должным образом, но похоже, что саму обратную косую черту нужно экранировать сначала для Scala, а затем затем для SQL.

Я предполагаю, что это может быть полезно для вставки управляющих символов (например, новой строки) в сам SQL-запрос. Я просто запутался, изменилось ли это где-то со Spark 1.5 на 2.1?

Я довольно много гуглил для этого, но ничего не нашел. Либо что-то изменилось, либо код моего коллеги работает непреднамеренно.

Я также пробовал это с Python/pyspark, и применяется то же условие - в SQL необходимы двойные обратные косые черты.

Кто-нибудь может это объяснить?

Я использую относительно простую установку в Windows со Spark 2.1.0, JDK 1.8.0_111 и Hadoop winutils.exe.


person Bjørn Nielsen    schedule 20.01.2017    source источник


Ответы (2)


Может быть потому, что обратная косая черта — это специальный символ, используемый для объединения многострочных SQL-запросов.

sql_1 = spark.sql("SELECT \
    1 AS `col1`, '{0}' AS `col2`".format(var_1))
person Shaman    schedule 23.10.2019

Вот несколько разных способов получить тот же результат:

Тройные кавычки

spark.sql("""SELECT split('What is this? A string I think', '\\?') AS result""").show(false)

Экранирование символа регулярного выражения

spark.sql("""SELECT split('What is this? A string I think', '\\Q?\\E') AS result""").show(false)

Pattern.quote

Предположим, ваша строка была в DataFrame.

val df = Seq(
  ("What is this? A string I think")
).toDF("your_string")

Вы можете использовать функцию цитирования регулярных выражений Java, чтобы разделить строку следующим образом:

import java.util.regex.Pattern
import org.apache.spark.sql.functions._

df
  .withColumn("split_string", split($"your_string", Pattern.quote("?")))
  .show(false)

Вот результат:

+------------------------------+---------------------------------+
|your_string                   |split_string                     |
+------------------------------+---------------------------------+
|What is this? A string I think|[What is this,  A string I think]|
+------------------------------+---------------------------------+

См. эту публикацию для получения дополнительной информации.

person Powers    schedule 17.01.2021