/
template.go
127 lines (107 loc) · 2.94 KB
/
template.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package ingest
import (
"bytes"
"fmt"
"strconv"
"strings"
"text/template"
"github.com/hans-m-song/archive-ingest/pkg/parse"
"github.com/sirupsen/logrus"
)
func createTemplate(name, text string) *template.Template {
template, err := template.New(name).Parse(text)
if err != nil {
logrus.WithFields(logrus.Fields{"name": name}).Fatal("error creating template")
}
return template
}
var (
templateInsertName = createTemplate("InsertName", `{{"" -}}
WITH tmp AS (
INSERT INTO {{.Table}}(name)
VALUES('{{.Value}}')
ON CONFLICT ON CONSTRAINT {{.Table}}_name_key DO NOTHING
RETURNING {{.Table}}_id
)
SELECT {{.Table}}_id FROM tmp
UNION ALL
SELECT {{.Table}}_id FROM {{.Table}}
WHERE name = '{{.Value}}'`,
)
templateCreateTable = createTemplate("CreateTable", `{{"" -}}
CREATE TABLE IF NOT EXISTS {{.Table}} (
{{.Table}}_id integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
{{- range $i, $element := .Columns}}
{{- if $i}}, {{end}}
{{$element}}{{end}}
)`,
)
templateInsertEntity = createTemplate("InsertEntity", `{{"" -}}
INSERT INTO entity
(filepath, filename, title, authors, tags, publisher_id, collection_id)
VALUES (
'{{.Filepath}}',
'{{.Filename}}',
'{{.Title}}',
'{{.Authors}}',
'{{.Tags}}',
{{.PublisherId}},
{{.CollectionId}}
)
ON CONFLICT (filepath, filename) DO NOTHING
RETURNING entity_id`,
)
)
func templateToString(template *template.Template, data interface{}) string {
buf := &bytes.Buffer{}
if err := template.Execute(buf, data); err != nil {
logrus.WithField("err", err).Fatal("error executing template")
}
return buf.String()
}
func createTableQuery(name string, columns ...string) string {
data := map[string]interface{}{"Table": name, "Columns": columns}
return templateToString(templateCreateTable, data)
}
func insertNameQuery(table, value string) string {
data := map[string]interface{}{"Table": table, "Value": value}
return templateToString(templateInsertName, data)
}
func constraintUnique(columns ...string) string {
return fmt.Sprintf(
"UNIQUE (%s)",
strings.Join(columns, ", "),
)
}
func constraintFk(name string) string {
return fmt.Sprintf(
`CONSTRAINT fk_%s_id FOREIGN KEY(%s_id) REFERENCES %s(%s_id)`,
name, name, name, name,
)
}
func arrayValue(values []int) string {
builder := strings.Builder{}
for i, value := range values {
if i > 0 {
builder.WriteString(",")
}
builder.WriteString(strconv.Itoa(value))
}
return fmt.Sprintf(`{%s}`, builder.String())
}
type InsertEntityParams struct {
Authors, Tags []int
PublisherId, CollectionId int
}
func insertEntityQuery(entity parse.Entity, params InsertEntityParams) string {
data := map[string]interface{}{
"Filepath": entity.Filepath,
"Filename": entity.Filename,
"Title": entity.Title,
"Authors": arrayValue(params.Authors),
"Tags": arrayValue(params.Tags),
"PublisherId": params.PublisherId,
"CollectionId": params.CollectionId,
}
return templateToString(templateInsertEntity, data)
}