Code generation for structs for tables

This commit is contained in:
Pavle Kosutic
2021-12-10 09:19:47 +01:00
committed by Michal Jan Matczuk
parent 3e151149a0
commit 2942397ab6
5 changed files with 149 additions and 5 deletions

View File

@@ -2,7 +2,12 @@
package {{.PackageName}}
import "github.com/scylladb/gocqlx/v2/table"
import (
"github.com/scylladb/gocqlx/v2/table"
{{- range .Imports}}
"{{.}}"
{{- end}}
)
// Table models.
var (
@@ -30,3 +35,27 @@ var (
{{end}}
{{end}}
)
{{with .UserTypes}}
{{range .}}
{{- $type_name := .Name | camelize}}
{{- $field_types := .FieldTypes}}
type {{$type_name}}Type struct {
{{- range $index, $element := .FieldNames}}
{{- $type := index $field_types $index}}
{{. | camelize}} {{getNativeTypeSting $type | mapScyllaToGoType}}
{{- end}}
}
{{- end}}
{{- end}}
{{with .Tables}}
{{range .}}
{{- $model_name := .Name | camelize}}
type {{$model_name}}Struct struct {
{{- range .Columns}}
{{.Name | camelize}} {{.Validator | mapScyllaToGoType}}
{{- end}}
}
{{- end}}
{{- end}}

View File

@@ -0,0 +1,87 @@
package main
import (
"regexp"
"strconv"
"strings"
"github.com/gocql/gocql"
)
var types = map[string]string{
"ascii": "string",
"bigint": "int64",
"blob": "[]byte",
"boolean": "bool",
"counter": "int",
"date": "string",
"decimal": "float32",
"double": "float64",
"duration": "unit32",
"float": "float32",
"inet": "string",
"int": "int32",
"smallint": "int16",
"text": "string",
"time": "uint32",
"timestamp": "uint32",
"timeuuid": "string",
"tinyint": "int8",
"uuid": "gocql.UUID",
"varchar": "string",
"varint": "int64",
}
func mapScyllaToGoType(s string) string {
mapRegex := regexp.MustCompile(`map<([a-z]*), ([a-z]*)>`)
setRegex := regexp.MustCompile(`set<([a-z]*)>`)
listRegex := regexp.MustCompile(`list<([a-z]*)>`)
tupleRegex := regexp.MustCompile(`tuple<(?:([a-z]*),? ?)*>`)
match := mapRegex.FindAllStringSubmatch(s, -1)
if match != nil {
key := match[0][1]
value := match[0][2]
return "map[" + types[key] + "]" + types[value]
}
match = setRegex.FindAllStringSubmatch(s, -1)
if match != nil {
key := match[0][1]
return "[]" + types[key]
}
match = listRegex.FindAllStringSubmatch(s, -1)
if match != nil {
key := match[0][1]
return "[]" + types[key]
}
match = tupleRegex.FindAllStringSubmatch(s, -1)
if match != nil {
tuple := match[0][0]
subStr := tuple[6 : len(tuple)-1]
types := strings.Split(subStr, ", ")
typeStr := "struct {\n"
for i, t := range types {
typeStr = typeStr + "\t\tFiled" + strconv.Itoa(i+1) + " " + mapScyllaToGoType(t) + "\n"
}
typeStr = typeStr + "\t}"
return typeStr
}
t, exists := types[s]
if exists {
return t
}
return camelize(s) + "Type"
}
func getNativeTypeSting(t gocql.NativeType) string {
return t.String()
}

View File

@@ -5,7 +5,6 @@ import (
_ "embed"
"flag"
"fmt"
"go/format"
"html/template"
"io/ioutil"
"log"
@@ -74,22 +73,36 @@ func renderTemplate(md *gocql.KeyspaceMetadata) ([]byte, error) {
t, err := template.
New("keyspace.tmpl").
Funcs(template.FuncMap{"camelize": camelize}).
Funcs(template.FuncMap{"mapScyllaToGoType": mapScyllaToGoType}).
Funcs(template.FuncMap{"getNativeTypeSting": getNativeTypeSting}).
Parse(keyspaceTmpl)
if err != nil {
log.Fatalln("unable to parse models template:", err)
}
imports := make([]string, 0)
for _, t := range md.Tables {
for _, c := range t.Columns {
if c.Validator == "uuid" && !existsInSlice(imports, "github.com/gocql/gocql") {
imports = append(imports, "github.com/gocql/gocql")
}
}
}
buf := &bytes.Buffer{}
data := map[string]interface{}{
"PackageName": *flagPkgname,
"Tables": md.Tables,
"UserTypes": md.UserTypes,
"Imports": imports,
}
if err = t.Execute(buf, data); err != nil {
return nil, fmt.Errorf("template: %w", err)
}
return format.Source(buf.Bytes())
//return format.Source(buf.Bytes())
return buf.Bytes(), nil
}
func createSession() (gocqlx.Session, error) {
@@ -106,3 +119,13 @@ func createSession() (gocqlx.Session, error) {
func clusterHosts() []string {
return strings.Split(*flagCluster, ",")
}
func existsInSlice(s []string, v string) bool {
for _, i := range s {
if v == i {
return true
}
}
return false
}