-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3d7031d
Showing
8 changed files
with
307 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
name: release | ||
on: | ||
release: | ||
types: [published] | ||
|
||
jobs: | ||
update: | ||
name: build | ||
runs-on: macOS-latest | ||
steps: | ||
- name: ⬇️ Checkout | ||
uses: actions/checkout@master | ||
with: | ||
fetch-depth: 1 | ||
- name: 🏗 swiftbuild | ||
run: | | ||
swift build -c debug | ||
- name: 📦 Build archive | ||
run: | | ||
REPOSITORY_NAME=$(jq --raw-output '.repository.name' $GITHUB_EVENT_PATH) | ||
zip -r $REPOSITORY_NAME.zip .build/debug/$REPOSITORY_NAME | ||
- name: ⬆️ Upload to Release | ||
run: | | ||
REPOSITORY_NAME=$(jq --raw-output '.repository.name' $GITHUB_EVENT_PATH) | ||
ARTIFACT=./$REPOSITORY_NAME.zip | ||
AUTH_HEADER="Authorization: token $GITHUB_TOKEN" | ||
CONTENT_LENGTH_HEADER="Content-Length: $(stat -f%z "$ARTIFACT")" | ||
CONTENT_TYPE_HEADER="Content-Type: application/zip" | ||
RELEASE_ID=$(jq --raw-output '.release.id' $GITHUB_EVENT_PATH) | ||
FILENAME=$(basename $ARTIFACT) | ||
UPLOAD_URL="https://uploads.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID/assets?name=$FILENAME" | ||
echo "$UPLOAD_URL" | ||
curl -sSL -XPOST \ | ||
-H "$AUTH_HEADER" -H "$CONTENT_LENGTH_HEADER" -H "$CONTENT_TYPE_HEADER" \ | ||
--upload-file "$ARTIFACT" "$UPLOAD_URL" | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
name: Swift | ||
|
||
on: | ||
push: | ||
branches: [ master ] | ||
pull_request: | ||
branches: [ master ] | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: macos-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Build | ||
run: swift build -v |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
included: | ||
- Sources | ||
|
||
# rule identifiers to exclude from running | ||
disabled_rules: | ||
- cyclomatic_complexity | ||
- large_tuple | ||
- todo | ||
|
||
shorthand_operator: warning | ||
|
||
# configurable rules can be customized from this configuration file | ||
line_length: | ||
- 200 | ||
- 250 | ||
|
||
function_body_length: | ||
- 50 | ||
- 100 | ||
|
||
file_length: | ||
- 500 | ||
- 600 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// swift-tools-version:5.1 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "cd2sql", | ||
products: [ | ||
.executable( | ||
name: "cd2sql", targets: ["cd2sql"] | ||
) | ||
], | ||
dependencies: [ | ||
.package(url: "https://github.com/phimage/MomXML" , .upToNextMajor(from: "1.1.0")), | ||
.package(url: "https://github.com/apple/swift-argument-parser", from: "0.0.6"), | ||
.package(url: "https://github.com/nvzqz/FileKit.git", from: "6.0.0") | ||
], | ||
targets: [ | ||
.target( | ||
name: "cd2sql", | ||
dependencies: ["MomXML", "ArgumentParser", "FileKit"], | ||
path: "Sources" | ||
) | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# CoreData to SQL | ||
|
||
![Swift](https://github.com/phimage/cd2sql/workflows/Swift/badge.svg) | ||
![release](https://github.com/phimage/cd2sql/workflows/release/badge.svg) | ||
|
||
Convert CoreData model to SQL | ||
|
||
## Install | ||
|
||
### Using release | ||
|
||
Go to https://github.com/phimage/cd2sql/releases and take the last binary for macOS cd2sql.zip | ||
|
||
### Using sources | ||
|
||
``` | ||
git clone https://github.com/phimage/cd2sql.git | ||
cd cd2sql | ||
swift build -c release | ||
``` | ||
|
||
Binary result in `.build/release/cd2sql` | ||
|
||
## Usage | ||
|
||
``` | ||
cd2sql <core data model> | ||
``` | ||
|
||
### example | ||
|
||
``` | ||
cd2sql /path/to/MyModel.xcdatamodeld | ||
``` | ||
|
||
```sql | ||
CREATE TABLE Personne ( | ||
FirstName VARCHAR, | ||
LastName VARCHAR, | ||
ID INTEGER PRIMARY KEY | ||
); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// | ||
// Command.swift | ||
// | ||
// Created by phimage on 15/05/2020. | ||
// | ||
|
||
import Foundation | ||
import ArgumentParser | ||
import MomXML | ||
import SWXMLHash | ||
import FileKit | ||
|
||
struct Command: ParsableCommand { | ||
|
||
static let configuration = CommandConfiguration(abstract: "Transform core data model to SQL") | ||
|
||
@Option(help: "The core data model path.") | ||
var path: String? | ||
|
||
@Argument(help: "The core data model path.") | ||
var pathArg: String? | ||
|
||
@Option(default: "", help: "Format sush as 'sqlite'") | ||
var format: String? // SQLite | ||
|
||
@Option(default: "keyMapping", help: "Search table and field names inside userinfo using this key") | ||
var mapping: String? | ||
|
||
@Option(help: "userinfo key used to find primary key (default: primaryKey)") | ||
var primaryKey: String? | ||
|
||
// @Flag [IF NOT EXISTS] | ||
|
||
func validate() throws { | ||
guard let path = self.path ?? self.pathArg else { | ||
throw ValidationError("'<path>' of core data model not specified.") | ||
} | ||
guard Path(path).exists else { | ||
throw ValidationError("'<path>' \(path) doesn't not exist.") | ||
} | ||
} | ||
|
||
func run() throws { | ||
var modelURL = URL(fileURLWithPath: self.path ?? self.pathArg ?? "") | ||
if modelURL.pathExtension == "xcdatamodeld" { | ||
modelURL = modelURL.appendingPathComponent("\(modelURL.deletingPathExtension().lastPathComponent).xcdatamodel") | ||
} | ||
if modelURL.pathExtension == "xcdatamodel" { | ||
modelURL = modelURL.appendingPathComponent("contents") | ||
} | ||
|
||
let xmlString = try String(contentsOf: modelURL) | ||
let xml = SWXMLHash.parse(xmlString) | ||
guard let parsedMom = MomXML(xml: xml) else { | ||
error("Failed to parse \(modelURL)") | ||
return | ||
} | ||
let sqliteLite = format == "sqlite" | ||
|
||
for entity in parsedMom.model.entities { | ||
let tableName = entity.name(sqlite: sqliteLite, mapping: mapping) | ||
var sql = "CREATE TABLE \(tableName) (\n" | ||
let primaryKey = entity.userInfo[self.primaryKey ?? "primaryKey"] | ||
|
||
var first = true | ||
for attribute in entity.attributes { | ||
if first { | ||
first = false | ||
} else { | ||
sql += ",\n" | ||
} | ||
let attributeName = attribute.name(sqlite: sqliteLite, mapping: mapping) | ||
sql += " \(attributeName) \(attribute.attributeType.sqliteName)" | ||
if !attribute.isOptional { | ||
sql += " NOT NULL" | ||
} | ||
if attributeName == primaryKey { | ||
sql += " PRIMARY KEY" | ||
} | ||
} | ||
sql += "\n);\n" | ||
log(sql) | ||
} | ||
} | ||
|
||
func log(_ message: String) { | ||
print(message) | ||
} | ||
|
||
func error(_ message: String) { | ||
print("❌ error: \(message)") // TODO: output in stderr | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import Foundation | ||
import MomXML | ||
|
||
protocol MomType { | ||
var name: String {get} | ||
var sqliteName: String {get} | ||
var userInfo: MomUserInfo {get} | ||
} | ||
|
||
extension MomEntity: MomType { | ||
|
||
var sqliteName: String { | ||
return "Z\(name.uppercased())" | ||
} | ||
} | ||
extension MomAttribute: MomType { | ||
|
||
var sqliteName: String { | ||
return "Z\(name.uppercased())" | ||
} | ||
} | ||
|
||
extension MomType { | ||
func name(sqlite: Bool, mapping: String?) -> String { | ||
if sqlite { | ||
return self.sqliteName | ||
} else { | ||
if let mapping = mapping, let name = self.userInfo[mapping] { | ||
return name | ||
} | ||
return self.name | ||
} | ||
} | ||
} | ||
|
||
extension MomAttribute.AttributeType { | ||
|
||
var sqliteName: String { | ||
switch self { | ||
case .string: | ||
return "VARCHAR" | ||
case .date: | ||
return "TIMESTAMP" | ||
case .integer32: | ||
return "INTEGER" | ||
case .boolean: | ||
return "INTEGER" | ||
case .binary, .transformable: | ||
return "BLOB" | ||
default: | ||
return self.rawValue.uppercased() | ||
} | ||
} | ||
|
||
} | ||
|
||
extension MomUserInfo { | ||
|
||
subscript(key: String) -> String? { | ||
for userInfo in self.entries { | ||
if userInfo.key == key { | ||
return userInfo.value | ||
} | ||
} | ||
return nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// Run command | ||
Command.main() |