Parse a new dump format

This commit is contained in:
theaspect 2025-04-15 04:25:35 +07:00
parent 18bbafea0a
commit 95ce5a64e7
3 changed files with 66 additions and 41 deletions

View File

@ -6,7 +6,7 @@ plugins {
} }
group = "me.blzr" group = "me.blzr"
version = "1.0-SNAPSHOT" version = "1.1"
repositories { repositories {
mavenCentral() mavenCentral()
@ -14,12 +14,13 @@ repositories {
dependencies { dependencies {
implementation("me.alllex.parsus:parsus-jvm:0.6.1") implementation("me.alllex.parsus:parsus-jvm:0.6.1")
implementation("info.picocli:picocli:4.7.6")
testImplementation(kotlin("test")) testImplementation(kotlin("test"))
} }
application { application {
mainClass.set("me.blzr.apex.MainKt") mainClass.set("me.blzr.apex.Main")
} }
tasks.test { tasks.test {

View File

@ -1,6 +1,9 @@
package me.blzr.apex package me.blzr.apex
import me.alllex.parsus.parser.getOrElse import me.alllex.parsus.parser.getOrElse
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.Option
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.FileOutputStream import java.io.FileOutputStream
@ -10,57 +13,78 @@ import kotlin.io.path.deleteIfExists
import kotlin.io.path.listDirectoryEntries import kotlin.io.path.listDirectoryEntries
import kotlin.system.exitProcess import kotlin.system.exitProcess
fun main(vararg args: String) { @Command(name = "apex-ddl-splitter", version = ["1.1"], mixinStandardHelpOptions = true)
val (input, output) = when (args.size) { class Main : Runnable {
1 -> args[0] to "${args[0].let { if (it.endsWith(".sql")) it.dropLast(4) else it }}/out/" @Option(names = ["-i", "--input"], description = ["Input SQL file"])
2 -> args[0] to args[1] lateinit var input: String
else -> {
println("apex-ddl-splitter input.sql [out folder]") @Option(names = ["-o", "--output"], description = ["Output folder. By default, './out'"])
exitProcess(0) var output: String? = null
@Option(names = ["-s", "--split"], description = ["Split. By default, '\\s*;$'", "Previous Oracle used '^/$'"])
var split: String = "\\s*;$"
companion object {
@JvmStatic
fun main(args: Array<String>) {
val exitCode: Int = CommandLine(Main()).execute(*args)
exitProcess(exitCode)
} }
} }
val ins = FileInputStream(input) override fun run() {
output = output ?: ((if (input.endsWith(".sql")) input.dropLast(4) else input) + "/out/")
val text = ins.bufferedReader().readText() val ins = FileInputStream(input)
val nodes = text.split(Regex("^/$", RegexOption.MULTILINE)).filter { it.isNotBlank() } val text = ins.bufferedReader().readText()
println("We have ${nodes.size} nodes")
val parser = OraDumpGrammar() val nodes = text.split(Regex(split, RegexOption.MULTILINE)).filter { it.isNotBlank() }
println("We have ${nodes.size} nodes")
val parsed: Map<String, Ora> = nodes.associateWith { node -> val parser = OraDumpGrammar()
parser.parse(node).getOrElse {
println(node)
throw IllegalArgumentException(it.toString())
}
}
val outputPath = Path(output).createDirectories() val parsed: Map<String, Ora> = nodes.associateWith { node ->
println("Create $outputPath") parser.parse(node).getOrElse {
println(node)
outputPath.listDirectoryEntries("*.sql").forEach { entry -> throw IllegalArgumentException(it.toString())
println("Delete $entry")
entry.deleteIfExists()
}
FileOutputStream(File(output, "dict.sql")).bufferedWriter().use { dict ->
parsed.entries.forEachIndexed { index, (text, type) ->
println("Writing ${type.fileName}")
val outputFile = File(output, type.fileName)
if (outputFile.exists()) {
throw IllegalArgumentException("File already exists $outputFile")
} }
}
dict.write("-- ${type.fileName}\n") val outputPath = Path(output!!).createDirectories()
println("Create $outputPath")
FileOutputStream(outputFile).bufferedWriter().use { outputPath.listDirectoryEntries("*.sql").forEach { entry ->
it.write(text.trim()) println("Delete $entry")
entry.deleteIfExists()
}
FileOutputStream(File(output, "dict.sql")).bufferedWriter().use { dict ->
parsed.entries.forEachIndexed { index, (text, type) ->
println("Writing ${type.fileName}")
var outputFile = File(output, type.fileName)
if (outputFile.exists()) {
for (i in 1..10) {
val anotherName = File(output, type.fileName.dropLast(".sql".length) + "-duplicate-$i.sql")
if (i == 10) {
throw IllegalArgumentException("File already exists $outputFile")
} else if (!anotherName.exists()) {
outputFile = anotherName
break
}
}
}
dict.write("-- ${type.fileName}\n")
FileOutputStream(outputFile).bufferedWriter().use {
it.write(text.trim())
}
} }
} }
} }
} }

View File

@ -46,7 +46,7 @@ class OraDumpGrammar() : Grammar<Ora>(ignoreCase = true, debugMode = true) {
val sequence = literalToken("sequence") val sequence = literalToken("sequence")
val quote = literalToken("\"") val quote = literalToken("\"")
val name = regexToken("\\w+") val name = regexToken("[\\w$]+")
val remaining = regexToken(Regex(".*", RegexOption.DOT_MATCHES_ALL)) val remaining = regexToken(Regex(".*", RegexOption.DOT_MATCHES_ALL))
val quoted by -quote * ref(::name) * -quote map { it.text } val quoted by -quote * ref(::name) * -quote map { it.text }