Skip to content

Commit

Permalink
Merge pull request #12 from k1LoW/add-output-dot
Browse files Browse the repository at this point in the history
Add `tbls dot` command
  • Loading branch information
k1LoW authored May 27, 2018
2 parents 4902bb6 + c9e0697 commit 8cf9904
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Usage:
Available Commands:
diff diff database and document
doc document a database
dot generate dot file
help Help about any command
version print tbls version

Expand Down
12 changes: 8 additions & 4 deletions cmd/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ import (
"os"
)

// force is a flag on whether to force genarate
var force bool

// docCmd represents the doc command
var docCmd = &cobra.Command{
Use: "doc [DSN] [DOCUMENT_PATH]",
Expand Down Expand Up @@ -67,7 +64,13 @@ var docCmd = &cobra.Command{
}
}

err = md.Output(s, outputPath, force)
switch outputFormat {
case "md":
err = md.Output(s, outputPath, force)
default:
err = fmt.Errorf("Error: %s", "unsupported output format")
}

if err != nil {
fmt.Println(err)
os.Exit(1)
Expand All @@ -80,4 +83,5 @@ func init() {
docCmd.Flags().BoolVarP(&force, "force", "f", false, "force")
docCmd.Flags().BoolVarP(&sort, "sort", "", false, "sort")
docCmd.Flags().StringVarP(&additionalDataPath, "add", "a", "", "additional schema data path")
docCmd.Flags().StringVarP(&outputFormat, "output", "o", "md", "output format")
}
80 changes: 80 additions & 0 deletions cmd/dot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright © 2018 Ken'ichiro Oyama <k1lowxb@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package cmd

import (
"fmt"
"github.com/k1LoW/tbls/db"
"github.com/k1LoW/tbls/output/dot"
"github.com/spf13/cobra"
"os"
)

// dotCmd represents the doc command
var dotCmd = &cobra.Command{
Use: "dot [DSN] [OUTPUT_PATH]",
Short: "generate dot file",
Long: `'tbls dot' analyzes a database and generate dot file.`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) != 2 {
return fmt.Errorf("Error: %s", "requires two args")
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
dsn := args[0]
outputPath := args[1]
s, err := db.Analyze(dsn)
if err != nil {
fmt.Println(err)
os.Exit(1)
}

if additionalDataPath != "" {
err = s.LoadAdditionalRelations(additionalDataPath)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}

if sort {
err = s.Sort()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}

err = dot.Output(s, outputPath, force)

if err != nil {
fmt.Println(err)
os.Exit(1)
}
},
}

func init() {
rootCmd.AddCommand(dotCmd)
dotCmd.Flags().BoolVarP(&force, "force", "f", false, "force")
dotCmd.Flags().StringVarP(&additionalDataPath, "add", "a", "", "additional schema data path")
}
6 changes: 6 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,18 @@ import (
"github.com/spf13/cobra"
)

// force is a flag on whether to force genarate
var force bool

// sort is a flag on whether to sort tables, columns, and more
var sort bool

// additionalDataPath is a additional data path
var additionalDataPath string

// outputFormat is output format
var outputFormat string

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "tbls",
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
)

//go:generate go-assets-builder -p md -s="/output/md/templates" output/md/templates -o output/md/templates.go
//go:generate go-assets-builder -p dot -s="/output/dot/templates" output/dot/templates -o output/dot/templates.go

func main() {
cmd.Execute()
Expand Down
50 changes: 50 additions & 0 deletions output/dot/dot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package dot

import (
"fmt"
"github.com/k1LoW/tbls/schema"
"io/ioutil"
"os"
"path/filepath"
"text/template"
)

// Output generate dot file for full relation.
func Output(s *schema.Schema, path string, force bool) error {
fullPath, err := filepath.Abs(path)
if err != nil {
return err
}

if !force && outputExists(s, fullPath) {
return fmt.Errorf("Error: %s", "output file already exists.")
}

file, err := os.Create(filepath.Join(fullPath, "schema.dot"))
defer file.Close()
if err != nil {
return err
}
f, _ := Assets.Open(filepath.Join("/", "schema.dot.tmpl"))
bs, _ := ioutil.ReadAll(f)
tmpl, err := template.New("index").Parse(string(bs))
if err != nil {
return err
}
err = tmpl.Execute(file, map[string]interface{}{
"Schema": s,
})
if err != nil {
return err
}
fmt.Printf("%s\n", filepath.Join(path, "schema.dot"))

return nil
}

func outputExists(s *schema.Schema, path string) bool {
if _, err := os.Lstat(filepath.Join(path, "schema.dot")); err == nil {
return true
}
return false
}
23 changes: 23 additions & 0 deletions output/dot/templates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dot

import (
"time"

"github.com/jessevdk/go-assets"
)

var _Assets21532ae17ad95976ac467eeaeab81f2bb1d537e4 = "digraph {{ .Schema.Name }} {\n // Config\n graph [rankdir=TB, layout=dot, fontname=\"Arial\"];\n node [shape=record, fontsize=14, margin=0.6, fontname=\"Arial\"];\n edge [fontsize=10, labelfloat=false, splines=none, fontname=\"Arial\"];\n\n // Tables\n {{- range $i, $t := .Schema.Tables }}\n {{ $t.Name }} [shape=none, label=<<table border=\"0\" cellborder=\"1\" cellspacing=\"0\" cellpadding=\"6\">\n <tr><td bgcolor=\"#EFEFEF\"><font face=\"Arial Bold\" point-size=\"18\">{{ $t.Name }}</font> <font color=\"#666666\">[{{ $t.Type }}]</font></td></tr>\n {{- range $ii, $c := $t.Columns }}\n <tr><td port=\"{{ $c.Name }}\" align=\"left\">{{ $c.Name }} <font color=\"#666666\">[{{ $c.Type }}]</font></td></tr>\n {{- end }}\n </table>>];\n {{- end }}\n\n // Relations\n {{- range $j, $r := .Schema.Relations }}\n {{ $r.Table.Name }}:{{ $c := index $r.Columns 0 }}{{ $c.Name }} -> {{ $r.ParentTable.Name }}:{{ $pc := index $r.ParentColumns 0 }}{{ $pc.Name }} [dir=back, arrowtail=crow, taillabel=<<table cellpadding=\"5\" border=\"0\" cellborder=\"0\"><tr><td>{{ $r.Def }}</td></tr></table>>];\n {{- end }}\n}\n"

// Assets returns go-assets FileSystem
var Assets = assets.NewFileSystem(map[string][]string{"/": []string{"schema.dot.tmpl"}}, map[string]*assets.File{
"/schema.dot.tmpl": &assets.File{
Path: "/schema.dot.tmpl",
FileMode: 0x1a4,
Mtime: time.Unix(1527433545, 1527433545000000000),
Data: []byte(_Assets21532ae17ad95976ac467eeaeab81f2bb1d537e4),
}, "/": &assets.File{
Path: "/",
FileMode: 0x800001ed,
Mtime: time.Unix(1527433545, 1527433545000000000),
Data: nil,
}}, "")
21 changes: 21 additions & 0 deletions output/dot/templates/schema.dot.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
digraph {{ .Schema.Name }} {
// Config
graph [rankdir=TB, layout=dot, fontname="Arial"];
node [shape=record, fontsize=14, margin=0.6, fontname="Arial"];
edge [fontsize=10, labelfloat=false, splines=none, fontname="Arial"];

// Tables
{{- range $i, $t := .Schema.Tables }}
{{ $t.Name }} [shape=none, label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="6">
<tr><td bgcolor="#EFEFEF"><font face="Arial Bold" point-size="18">{{ $t.Name }}</font> <font color="#666666">[{{ $t.Type }}]</font></td></tr>
{{- range $ii, $c := $t.Columns }}
<tr><td port="{{ $c.Name }}" align="left">{{ $c.Name }} <font color="#666666">[{{ $c.Type }}]</font></td></tr>
{{- end }}
</table>>];
{{- end }}

// Relations
{{- range $j, $r := .Schema.Relations }}
{{ $r.Table.Name }}:{{ $c := index $r.Columns 0 }}{{ $c.Name }} -> {{ $r.ParentTable.Name }}:{{ $pc := index $r.ParentColumns 0 }}{{ $pc.Name }} [dir=back, arrowtail=crow, taillabel=<<table cellpadding="5" border="0" cellborder="0"><tr><td>{{ $r.Def }}</td></tr></table>>];
{{- end }}
}
4 changes: 2 additions & 2 deletions output/md/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var Assets = assets.NewFileSystem(map[string][]string{"/": []string{"index.md.tm
"/": &assets.File{
Path: "/",
FileMode: 0x800001ed,
Mtime: time.Unix(1526904993, 1526904993000000000),
Mtime: time.Unix(1527296235, 1527296235000000000),
Data: nil,
}, "/index.md.tmpl": &assets.File{
Path: "/index.md.tmpl",
Expand All @@ -24,6 +24,6 @@ var Assets = assets.NewFileSystem(map[string][]string{"/": []string{"index.md.tm
}, "/table.md.tmpl": &assets.File{
Path: "/table.md.tmpl",
FileMode: 0x1a4,
Mtime: time.Unix(1526904993, 1526904993000000000),
Mtime: time.Unix(1527296235, 1527296235000000000),
Data: []byte(_Assetsac44302fb6150a621aa9d04a0350aac972bf7e18),
}}, "")

0 comments on commit 8cf9904

Please # to comment.