jet/generator/internal/metadata/column_meta_data.go

176 lines
4.6 KiB
Go
Raw Normal View History

2019-07-27 10:40:30 +02:00
package metadata
import (
"database/sql"
"fmt"
2019-07-04 17:54:15 +02:00
"github.com/go-jet/jet/internal/utils"
"strings"
)
2019-08-14 12:50:31 +02:00
// ColumnMetaData struct
type ColumnMetaData struct {
Name string
IsNullable bool
DataType string
2019-04-03 19:21:46 +02:00
EnumName string
2019-08-14 12:50:31 +02:00
IsUnsigned bool
SqlBuilderColumnType string
GoBaseType string
GoModelType string
}
2019-08-17 18:32:01 +02:00
// NewColumnMetaData create new column meta data that describes one column in SQL database
2019-08-14 12:50:31 +02:00
func NewColumnMetaData(name string, isNullable bool, dataType string, enumName string, isUnsigned bool) ColumnMetaData {
columnMetaData := ColumnMetaData{
Name: name,
IsNullable: isNullable,
DataType: dataType,
EnumName: enumName,
IsUnsigned: isUnsigned,
}
columnMetaData.SqlBuilderColumnType = columnMetaData.getSqlBuilderColumnType()
columnMetaData.GoBaseType = columnMetaData.getGoBaseType()
columnMetaData.GoModelType = columnMetaData.getGoModelType()
return columnMetaData
}
// getSqlBuilderColumnType returns type of jet sql builder column
func (c ColumnMetaData) getSqlBuilderColumnType() string {
switch c.DataType {
case "boolean":
2019-06-08 16:34:15 +02:00
return "Bool"
2019-07-27 10:40:30 +02:00
case "smallint", "integer", "bigint",
"tinyint", "mediumint", "int", "year": //MySQL
2019-06-08 16:34:15 +02:00
return "Integer"
case "date":
2019-06-08 16:34:15 +02:00
return "Date"
2019-07-27 10:40:30 +02:00
case "timestamp without time zone",
2019-07-29 18:08:53 +02:00
"timestamp", "datetime": //MySQL:
2019-06-08 16:34:15 +02:00
return "Timestamp"
case "timestamp with time zone":
2019-06-08 16:34:15 +02:00
return "Timestampz"
case "time without time zone",
"time": //MySQL
2019-06-08 16:34:15 +02:00
return "Time"
case "time with time zone":
2019-06-08 16:34:15 +02:00
return "Timez"
2019-07-27 10:40:30 +02:00
case "USER-DEFINED", "enum", "text", "character", "character varying", "bytea", "uuid",
"tsvector", "bit", "bit varying", "money", "json", "jsonb", "xml", "point", "interval", "line", "ARRAY",
"char", "varchar", "binary", "varbinary",
"tinyblob", "blob", "mediumblob", "longblob", "tinytext", "mediumtext", "longtext": // MySQL
2019-06-08 16:34:15 +02:00
return "String"
2019-07-29 18:08:53 +02:00
case "real", "numeric", "decimal", "double precision", "float",
"double": // MySQL
2019-06-08 16:34:15 +02:00
return "Float"
default:
2019-08-14 12:50:31 +02:00
fmt.Println("- [SQL Builder] Unsupported sql column '" + c.Name + " " + c.DataType + "', using StringColumn instead.")
2019-06-08 16:34:15 +02:00
return "String"
}
}
2019-08-14 12:50:31 +02:00
// getGoBaseType returns model type for column info.
func (c ColumnMetaData) getGoBaseType() string {
2019-05-20 17:37:55 +02:00
switch c.DataType {
2019-07-27 10:40:30 +02:00
case "USER-DEFINED", "enum":
2019-07-04 17:54:15 +02:00
return utils.ToGoIdentifier(c.EnumName)
2019-05-20 17:37:55 +02:00
case "boolean":
return "bool"
2019-07-27 10:40:30 +02:00
case "tinyint":
return "int8"
case "smallint",
"year":
2019-05-20 17:37:55 +02:00
return "int16"
2019-07-27 10:40:30 +02:00
case "integer",
"mediumint", "int": //MySQL
2019-05-20 17:37:55 +02:00
return "int32"
case "bigint":
return "int64"
2019-07-27 10:40:30 +02:00
case "date", "timestamp without time zone", "timestamp with time zone", "time with time zone", "time without time zone",
"timestamp", "datetime", "time": // MySQL
2019-05-20 17:37:55 +02:00
return "time.Time"
2019-07-27 10:40:30 +02:00
case "bytea",
2019-07-29 18:08:53 +02:00
"binary", "varbinary", "tinyblob", "blob", "mediumblob", "longblob": //MySQL
2019-05-20 17:37:55 +02:00
return "[]byte"
case "text", "character", "character varying", "tsvector", "bit", "bit varying", "money", "json", "jsonb",
2019-07-27 10:40:30 +02:00
"xml", "point", "interval", "line", "ARRAY",
2019-07-29 18:08:53 +02:00
"char", "varchar", "tinytext", "mediumtext", "longtext": // MySQL
2019-05-20 17:37:55 +02:00
return "string"
case "real":
return "float32"
2019-07-29 18:08:53 +02:00
case "numeric", "decimal", "double precision", "float",
"double": // MySQL
2019-05-20 17:37:55 +02:00
return "float64"
case "uuid":
return "uuid.UUID"
default:
2019-08-14 12:50:31 +02:00
fmt.Println("- [Model ] Unsupported sql column '" + c.Name + " " + c.DataType + "', using string instead.")
2019-05-20 17:37:55 +02:00
return "string"
}
}
// GoModelType returns model type for column info with optional pointer if
// column can be NULL.
2019-08-14 12:50:31 +02:00
func (c ColumnMetaData) getGoModelType() string {
typeStr := c.GoBaseType
2019-07-27 10:40:30 +02:00
if strings.Contains(typeStr, "int") && c.IsUnsigned {
typeStr = "u" + typeStr
}
if c.IsNullable {
2019-05-24 13:13:13 +02:00
return "*" + typeStr
}
2019-05-20 17:37:55 +02:00
2019-05-24 13:13:13 +02:00
return typeStr
}
// GoModelTag returns model field tag for column
2019-08-14 12:50:31 +02:00
func (c ColumnMetaData) GoModelTag(isPrimaryKey bool) string {
2019-06-12 12:47:30 +02:00
tags := []string{}
if isPrimaryKey {
tags = append(tags, "primary_key")
}
if len(tags) > 0 {
return "`sql:\"" + strings.Join(tags, ",") + "\"`"
}
return ""
}
2019-08-14 12:50:31 +02:00
func getColumnsMetaData(db *sql.DB, querySet DialectQuerySet, schemaName, tableName string) ([]ColumnMetaData, error) {
2019-07-27 10:40:30 +02:00
rows, err := db.Query(querySet.ListOfColumnsQuery(), schemaName, tableName)
if err != nil {
return nil, err
}
defer rows.Close()
2019-08-14 12:50:31 +02:00
ret := []ColumnMetaData{}
for rows.Next() {
2019-08-14 12:50:31 +02:00
var name, isNullable, dataType, enumName string
var isUnsigned bool
err := rows.Scan(&name, &isNullable, &dataType, &enumName, &isUnsigned)
if err != nil {
return nil, err
}
2019-08-14 12:50:31 +02:00
ret = append(ret, NewColumnMetaData(name, isNullable == "YES", dataType, enumName, isUnsigned))
}
err = rows.Err()
if err != nil {
return nil, err
}
return ret, nil
}