【问题标题】:SQL DDL to parse JSON schema fileSQL DDL 解析 JSON 模式文件
【发布时间】:2019-04-03 22:00:26
【问题描述】:

是否可以不使用任何工具,仅使用 Scala/Python/shell 脚本将 SQL DDL 语句解析为如下所示的简单 JSON 模式文件?

CREATE TABLE TEMP (
      ID INT,
      NAME STRING)

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

【问题讨论】:

    标签: python-3.x scala shell apache-spark


    【解决方案1】:

    您可以使用以下逻辑(Scala 代码)从 DDL 创建 JSON 格式的字符串。生成字符串后,将其转换为Dataframe。然后使用 Dataframe's 内置 API 调用 write.json 将这个 Dataframe 作为 JSON 文件保存到 HDFS/Amazon S3 中

    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>")
    

    如果您有任何问题,请告诉我。

    【讨论】:

    • 它非常适合我。如果我在具有多个 DDL 语句的文件中有折痕 sql,并且在同一文件中需要避免在两者之间有一些 cmets。例如:---table 1 createSQL1 --table 2 createSql2 --table createSql3
    【解决方案2】:

    使用一些匹配,例如此处描述的:How to pattern match using regular expression in 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))
    

    【讨论】:

      【解决方案3】:

      使用 scala.util.parsing.combinator 包,您可以像这样使用 DDL 定义 Lexer 和 Grammer 解析器,

      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 字符串解析为 lexel 流以供进一步处理。阅读文档,您将能够定义您的 SQL DDL 解析器。

      【讨论】:

        【解决方案4】:

        我们刚刚在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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-25
          • 2017-01-22
          • 2012-06-03
          • 2016-06-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多