2
votes

SQL DDL pour analyser le fichier de schéma JSON

Une instruction SQL DDL peut-elle être analysée en un simple fichier de schéma JSON comme indiqué ci-dessous sans utiliser d'outils, uniquement des scripts Scala / Python / shell?

CREATE TABLE TEMP (
      ID INT,
      NAME STRING)

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


0 commentaires

4 Réponses :


0
votes

Avec quelques correspondances comme par exemple décrites ici: Comment créer un modèle match en utilisant une expression régulière dans Scala? le code pour cela pourrait ressembler à celui ci-dessous, en supposant que votre expression initiale est passée sous forme de séquence de lignes (notez que JSONObject tel qu'utilisé ci-dessous est obsolète, remplacez-le par une alternative).

val data: (String, Seq[(String, String)]) = Parser.parse(Seq("CREATE TABLE TEMP (", "ID INT,", "NAME STRING)"))
      println(Parser.toJson(data._1, data._2))

Pour tester cela avec votre chaîne de test:

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


0 commentaires

1
votes

Vous pouvez créer une chaîne au format JSON à partir de votre DDL en utilisant la logique ci-dessous (code Scala). Une fois la chaîne créée, elle est convertie en Dataframe . Ce Dataframe est ensuite enregistré dans un HDFS / Amazon S3 en tant que fichier JSON à l'aide de l'API intégrée de Dataframe appelée 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>")


1 commentaires

Cela a parfaitement fonctionné pour moi. Si j'ai un pli sql dans un fichier avec plusieurs instructions DDL et qu'il y a des commentaires entre les deux à éviter dans le même fichier. ex: --- table 1 createSQL1 --table 2 createSql2 --table createSql3



0
votes

Avec le package scala.util.parsing.combinator, vous pouvez définir votre analyseur Lexer et Grammer avec DDL comme ceci,

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
} 

Le code ci-dessus serait utilisé pour analyser la chaîne JSON dans un flux lexel pour une autre procession. Lisez la documentation vous pourrez définir votre analyseur SQL DDL.


0 commentaires

0
votes

Nous venons de publier ce package dans https://github.com/deepstartup/jsonutils . Peut-être que vous le trouverez utile. Si vous avez besoin de nous pour mettre à jour quelque chose, ouvrez un JIRA.

Essayez:

    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 commentaires