schema and template functions
This commit is contained in:
		
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@@ -1,4 +1,2 @@
 | 
			
		||||
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
 | 
			
		||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 | 
			
		||||
github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg=
 | 
			
		||||
github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										67
									
								
								pfn.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								pfn.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "name":"computer",
 | 
			
		||||
        "columns":
 | 
			
		||||
            {
 | 
			
		||||
                "id":"integer",
 | 
			
		||||
                "name":"varchar(255)|comment",
 | 
			
		||||
                "description":"varchar(1000)",
 | 
			
		||||
                "os":"varchar(255)"
 | 
			
		||||
            }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name":"software",
 | 
			
		||||
        "columns":
 | 
			
		||||
            {
 | 
			
		||||
                "id":"integer",
 | 
			
		||||
                "name":"varchar(255)|comment",
 | 
			
		||||
                "description":"varchar(1000)",
 | 
			
		||||
                "licenseend":"date",
 | 
			
		||||
                "support":"varchar(255)",
 | 
			
		||||
                "company":"varchar(255)"
 | 
			
		||||
            }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name":"software_computer",
 | 
			
		||||
        "columns":
 | 
			
		||||
            {
 | 
			
		||||
                "id":"integer",
 | 
			
		||||
                "computer_id":"integer",
 | 
			
		||||
                "software_id":"integer"
 | 
			
		||||
            }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name":"person",
 | 
			
		||||
        "columns":
 | 
			
		||||
            {
 | 
			
		||||
                "id":"integer",
 | 
			
		||||
                "name":"varchar(255)",
 | 
			
		||||
                "firstname":"varchar(255)",
 | 
			
		||||
                "email":"varchar(255)",
 | 
			
		||||
                "mobile":"varchar(255)"
 | 
			
		||||
            }        
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name":"entity",
 | 
			
		||||
        "columns":
 | 
			
		||||
            {
 | 
			
		||||
                "id":"integer",
 | 
			
		||||
                "name":"varchar(255)",
 | 
			
		||||
                "type":"varchar(255)",
 | 
			
		||||
                "startdate":"date",
 | 
			
		||||
                "enddate":"date"
 | 
			
		||||
            }        
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name":"timetracking",
 | 
			
		||||
        "columns":
 | 
			
		||||
            {
 | 
			
		||||
                "id":"integer",
 | 
			
		||||
                "day":"date",
 | 
			
		||||
                "morning_entity_id":"integer",
 | 
			
		||||
                "afternoon_entity_id":"integer",
 | 
			
		||||
                "comment":"varchar(255)"
 | 
			
		||||
            }        
 | 
			
		||||
    }
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										163
									
								
								pg.go
									
									
									
									
									
								
							
							
						
						
									
										163
									
								
								pg.go
									
									
									
									
									
								
							@@ -2,8 +2,12 @@ package sqldb
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"html/template"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
@@ -29,6 +33,11 @@ type TableInfo struct {
 | 
			
		||||
	db      *Db
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Link struct {
 | 
			
		||||
	Source      string
 | 
			
		||||
	Destination string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open the database
 | 
			
		||||
func Open(driver string, url string) *Db {
 | 
			
		||||
	var database Db
 | 
			
		||||
@@ -135,6 +144,30 @@ func (t *TableInfo) GetSchema() (*TableInfo, error) {
 | 
			
		||||
	return &ti, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (db *Db) GetSchema() ([]TableInfo, error) {
 | 
			
		||||
	var res []TableInfo
 | 
			
		||||
	tables, err := db.ListTables()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err.Error())
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	for _, row := range tables {
 | 
			
		||||
		for _, element := range row {
 | 
			
		||||
			var ti TableInfo
 | 
			
		||||
			var fullti *TableInfo
 | 
			
		||||
			ti.Name = fmt.Sprintf("%v", element)
 | 
			
		||||
			ti.db = db
 | 
			
		||||
			fullti, err = ti.GetSchema()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println(err.Error())
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			res = append(res, *fullti)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (db *Db) ListTables() (Rows, error) {
 | 
			
		||||
	return db.QueryAssociativeArray("SELECT table_name :: varchar as name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name;")
 | 
			
		||||
}
 | 
			
		||||
@@ -220,6 +253,46 @@ func (t *TableInfo) DeleteColumn(name string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (db *Db) ImportSchema(filename string) {
 | 
			
		||||
	jsonFile, err := os.Open(filename)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer jsonFile.Close()
 | 
			
		||||
 | 
			
		||||
	byteValue, _ := ioutil.ReadAll(jsonFile)
 | 
			
		||||
 | 
			
		||||
	var jsonSource []TableInfo
 | 
			
		||||
	json.Unmarshal([]byte(byteValue), &jsonSource)
 | 
			
		||||
	for _, ti := range jsonSource {
 | 
			
		||||
		ti.db = db
 | 
			
		||||
		err = db.CreateTable(ti)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println(err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (db *Db) ClearImportSchema(filename string) {
 | 
			
		||||
	jsonFile, err := os.Open(filename)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer jsonFile.Close()
 | 
			
		||||
 | 
			
		||||
	byteValue, _ := ioutil.ReadAll(jsonFile)
 | 
			
		||||
 | 
			
		||||
	var jsonSource []TableInfo
 | 
			
		||||
	json.Unmarshal([]byte(byteValue), &jsonSource)
 | 
			
		||||
	for _, ti := range jsonSource {
 | 
			
		||||
		ti.db = db
 | 
			
		||||
		err = ti.DeleteTable()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println(err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (db *Db) ListSequences() (Rows, error) {
 | 
			
		||||
	return db.QueryAssociativeArray("SELECT sequence_name :: varchar FROM information_schema.sequences WHERE sequence_schema = 'public' ORDER BY sequence_name;")
 | 
			
		||||
}
 | 
			
		||||
@@ -340,7 +413,6 @@ func (t *TableInfo) UpdateOrInsert(record AssRow) (int, error) {
 | 
			
		||||
		t.Update(record)
 | 
			
		||||
		return id, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func removeLastChar(s string) string {
 | 
			
		||||
@@ -368,3 +440,92 @@ func (ar *AssRow) GetFloat(column string) float64 {
 | 
			
		||||
func Quote(str string) string {
 | 
			
		||||
	return pq.QuoteLiteral(str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (db *Db) SaveSchema(generatedFilename string) error {
 | 
			
		||||
	schema, err := db.GetSchema()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	file, _ := json.MarshalIndent(schema, "", " ")
 | 
			
		||||
	_ = ioutil.WriteFile(generatedFilename, file, 0644)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func buildLinks(schema []TableInfo) []Link {
 | 
			
		||||
	var links []Link
 | 
			
		||||
	for _, ti := range schema {
 | 
			
		||||
		fmt.Println(ti.Name)
 | 
			
		||||
		for column, _ := range ti.Columns {
 | 
			
		||||
			if strings.HasSuffix(column, "_id") {
 | 
			
		||||
				tokens := strings.Split(column, "_")
 | 
			
		||||
				linkedtable := tokens[len(tokens)-2]
 | 
			
		||||
				var link Link
 | 
			
		||||
				link.Source = ti.Name
 | 
			
		||||
				link.Destination = linkedtable
 | 
			
		||||
				links = append(links, link)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return links
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (db *Db) GenerateTemplate(templateFilename string, generatedFilename string) error {
 | 
			
		||||
	schema, err := db.GetSchema()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	links := buildLinks(schema)
 | 
			
		||||
	data := struct {
 | 
			
		||||
		Tbl []TableInfo
 | 
			
		||||
		Lnk []Link
 | 
			
		||||
	}{
 | 
			
		||||
		schema,
 | 
			
		||||
		links,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t, err := template.ParseFiles(templateFilename)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	f, err := os.Create(generatedFilename)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println("create file: ", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	err = t.Execute(f, data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (db *Db) GenerateTableTemplates(templateFilename string, outputFolder string, extension string) error {
 | 
			
		||||
	schema, err := db.GetSchema()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	for _, ti := range schema {
 | 
			
		||||
 | 
			
		||||
		t, err := template.ParseFiles(templateFilename)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println(err)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		f, err := os.Create(outputFolder + string(os.PathSeparator) + ti.Name + "." + extension)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println("create file: ", err)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		err = t.Execute(f, ti)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println(err)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								pg_test.go
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								pg_test.go
									
									
									
									
									
								
							@@ -12,7 +12,7 @@ func TestCreateTable(t *testing.T) {
 | 
			
		||||
	db := Open("postgres", "host=127.0.0.1 port=5432 user=test password=test dbname=test sslmode=disable")
 | 
			
		||||
	defer db.Close()
 | 
			
		||||
 | 
			
		||||
	jsonFile, err := os.Open("test_table.json")
 | 
			
		||||
	jsonFile, err := os.Open("testtype_table.json")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -171,7 +171,55 @@ func TestDeleteColumn(t *testing.T) {
 | 
			
		||||
func TestDeleteTable(t *testing.T) {
 | 
			
		||||
	db := Open("postgres", "host=127.0.0.1 port=5432 user=test password=test dbname=test sslmode=disable")
 | 
			
		||||
	defer db.Close()
 | 
			
		||||
 | 
			
		||||
	db.Table("test").DeleteTable()
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestImportSchema(t *testing.T) {
 | 
			
		||||
	db := Open("postgres", "host=127.0.0.1 port=5432 user=test password=test dbname=test sslmode=disable")
 | 
			
		||||
	defer db.Close()
 | 
			
		||||
	db.ImportSchema("pfn.json")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestClearImportSchema(t *testing.T) {
 | 
			
		||||
	db := Open("postgres", "host=127.0.0.1 port=5432 user=test password=test dbname=test sslmode=disable")
 | 
			
		||||
	defer db.Close()
 | 
			
		||||
	db.ClearImportSchema("pfn.json")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetSchema(t *testing.T) {
 | 
			
		||||
	db := Open("postgres", "host=127.0.0.1 port=5432 user=test password=test dbname=test sslmode=disable")
 | 
			
		||||
	defer db.Close()
 | 
			
		||||
	data, err := db.GetSchema()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	val, _ := json.Marshal(data)
 | 
			
		||||
	fmt.Println(string(val))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestSaveSchema(t *testing.T) {
 | 
			
		||||
	db := Open("postgres", "host=127.0.0.1 port=5432 user=test password=test dbname=test sslmode=disable")
 | 
			
		||||
	defer db.Close()
 | 
			
		||||
	err := db.SaveSchema("schema.json")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func TestGenerateTemplate(t *testing.T) {
 | 
			
		||||
	db := Open("postgres", "host=127.0.0.1 port=5432 user=test password=test dbname=test sslmode=disable")
 | 
			
		||||
	defer db.Close()
 | 
			
		||||
	err := db.GenerateTemplate("plantuml.tmpl", "schema.puml")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGenerateTableTemplate(t *testing.T) {
 | 
			
		||||
	db := Open("postgres", "host=127.0.0.1 port=5432 user=test password=test dbname=test sslmode=disable")
 | 
			
		||||
	defer db.Close()
 | 
			
		||||
	err := db.GenerateTableTemplates("table.tmpl", "gen", "html")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err.Error())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								plantuml.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								plantuml.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
@startuml
 | 
			
		||||
 | 
			
		||||
{{range .Tbl}}
 | 
			
		||||
entity {{.Name}} {
 | 
			
		||||
{{range $key, $value := .Columns}}  {{$key}} : {{$value}}
 | 
			
		||||
{{end}}}
 | 
			
		||||
{{end}}
 | 
			
		||||
 | 
			
		||||
{{range .Lnk}}
 | 
			
		||||
{{.Source}} ||..|| {{.Destination}}
 | 
			
		||||
{{end}}
 | 
			
		||||
 | 
			
		||||
@enduml
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								table.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								table.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
{{.Name}}
 | 
			
		||||
@@ -1,17 +1,10 @@
 | 
			
		||||
{
 | 
			
		||||
    "name":"testtype",
 | 
			
		||||
    "columns":[
 | 
			
		||||
    "columns":
 | 
			
		||||
        {
 | 
			
		||||
            "name":"id",
 | 
			
		||||
            "type":"integer"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name":"name",
 | 
			
		||||
            "type":"varchar(255)"
 | 
			
		||||
        },        
 | 
			
		||||
        {
 | 
			
		||||
            "name":"detail",
 | 
			
		||||
            "type":"varchar(255)"
 | 
			
		||||
            "id":"integer",
 | 
			
		||||
            "name":"varchar(255)",
 | 
			
		||||
            "detail":"varchar(255)"
 | 
			
		||||
        }
 | 
			
		||||
       ]
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user