SQL DDL для анализа файла схемы JSON - PullRequest
2 голосов
/ 04 апреля 2019

Может ли оператор SQL DDL быть проанализирован в простой файл схемы JSON, как показано ниже, без использования каких-либо инструментов, только сценарии Scala / Python / shell?

CREATE TABLE TEMP (
      ID INT,
      NAME STRING)

[
  {
    "tableName": "temp",
    "columns": [
      {
        "columnname": "id",
        "datatype": "int"
      },
      {
        "columnname": "name",
        "datatype": "string"
      }
    ]
  }
]

Ответы [ 4 ]

1 голос
/ 04 апреля 2019

Вы можете создать строку в форме JSON из вашего DDL, используя приведенную ниже логику (код Scala). Как только строка сделана, она конвертируется в Dataframe. Этот Dataframe затем сохраняется в HDFS / Amazon S3 в виде файла JSON с использованием встроенного API Dataframe's с именем write.json

.
import org.apache.spark.sql.types._
import spark.implicits._
val createSql = "CREATE TABLE TEMP (ID INT, NAME STRING)"
var jsonString = """[{"tableName":"""" + createSql.split(" ")(2).toLowerCase + "\"," + "\"columns\":["
createSql.split(s"\\(")(1).split(s"\\)")(0).split(",").map(r => {
jsonString += "{" + "\"columnname\": " + "\"" + r.trim.split(" ")(0).toLowerCase + "\"," + "\"datatype\": " + "\"" + r.trim.split(" ")(1).toLowerCase + "\"},"
})
jsonString = jsonString.patch(jsonString.lastIndexOf(','), "", 1) + "]}]"
val schema: StructType = null
val reader = spark.read
Option(schema).foreach(reader.schema)
val df = reader.json(sc.parallelize(Array(jsonString)))
df.coalesce(1).write.json("<targetlocation>")

Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы.

0 голосов
/ 01 июля 2019

Мы только что опубликовали этот пакет в https://github.com/deepstartup/jsonutils. Может быть, вы найдете его полезным. Если вам нужно что-то обновить, откройте JIRA.

Попытка:

    pip install DDLJ
    from DDLj import genddl
    genddl(*param1,param2,*param3,*param4)

Where
param1= JSON Schema File
param2=Database (Default Oracle)
Param3= Glossary file
Param4= DDL output script
0 голосов
/ 04 апреля 2019

С пакетом scala.util.parsing.combinator вы можете определить свой синтаксический анализатор Lexer и Grammer с помощью DDL следующим образом:

import scala.util.parsing.combinator._

class JSON extends JavaTokenParsers {
  def value: Parser[Any] = obj | arr | stringLiteral | floatingPointNumber | "null" | "true" | "false"
  def obj: Parser[Any] = "{"~repsep(member, ",")~"}"
  def arr: Parser[Any] = "["~repsep(value, ",")~"]"
  def member: Parser[Any] = stringLiteral~":"~value
} 

Приведенный выше код будет использоваться для разбора строки JSON в поток лекселей для дальнейшей обработки. Прочтите документ, и вы сможете определить свой парсер SQL DDL.

0 голосов
/ 04 апреля 2019

С некоторым соответствием, как, например, описано здесь: Как сопоставить шаблон с использованием регулярного выражения в Scala? код для этого может выглядеть следующим образом, при условии, что ваше первоначальное выражение передается в виде последовательности строк (примечание этот JSONObject, как он используется ниже, устарел, поэтому замените его каким-нибудь альтернативным).

object Parser {

    implicit class Regex(sc: StringContext) {
      def r = new util.matching.Regex(sc.parts.mkString, sc.parts.tail.map(_ => "x"): _*)
    }

    def toJson(tablename: String, columns: Seq[(String,String)]): String = {
      val columnList: List[JSONObject] = columns.toStream.map(x => JSONObject(Map("columnname" -> x._1, "datatype" -> x._2))).toList
      JSONArray(List(JSONObject(Map("tableName" -> tablename, "columns" -> JSONArray(columnList))))).toString()
    }

    def parse(lines: Seq[String]): (String, Seq[(String,String)]) = {
      lines.mkString("").toLowerCase match {
        case r"create\s+table\s+(\S+)${tablename}\s+\((.+)${columns}\).*" =>
          val columnWithType: immutable.Seq[(String, String)] = columns.split(",").toStream
            .map(x => x.split("\\s+"))
            .map(x => (x.head.toLowerCase, x(1).toLowerCase))
          (tablename, columnWithType)
        case _ => ("",Seq.empty)
      }
    }
  }

Чтобы проверить это с помощью тестовой строки:

val data: (String, Seq[(String, String)]) = Parser.parse(Seq("CREATE TABLE TEMP (", "ID INT,", "NAME STRING)"))
      println(Parser.toJson(data._1, data._2))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...