Additional documentation for sub packages.
This commit is contained in:
parent
b10270b502
commit
556578cec9
19 changed files with 111 additions and 77 deletions
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-jet/jet/generator/postgres"
|
"github.com/go-jet/jet/generator/postgres"
|
||||||
|
_ "github.com/lib/pq"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -50,11 +50,11 @@ func main() {
|
||||||
fmt.Println("Arguments: ")
|
fmt.Println("Arguments: ")
|
||||||
fmt.Println(args)
|
fmt.Println(args)
|
||||||
|
|
||||||
debugSql, err := stmt.DebugSql()
|
debugSQL, err := stmt.DebugSql()
|
||||||
panicOnError(err)
|
panicOnError(err)
|
||||||
|
|
||||||
fmt.Println("Debug sql: ")
|
fmt.Println("Debug sql: ")
|
||||||
fmt.Println(debugSql)
|
fmt.Println(debugSQL)
|
||||||
|
|
||||||
var dest []struct {
|
var dest []struct {
|
||||||
model.Actor
|
model.Actor
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DB is common database interface used by jet execution
|
||||||
type DB interface {
|
type DB interface {
|
||||||
Exec(query string, args ...interface{}) (sql.Result, error)
|
Exec(query string, args ...interface{}) (sql.Result, error)
|
||||||
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
|
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,12 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Query executes query with arguments over database connection with context and stores result into destination.
|
||||||
|
// Destination can be either pointer to struct or pointer to slice of structs.
|
||||||
func Query(db DB, context context.Context, query string, args []interface{}, destinationPtr interface{}) error {
|
func Query(db DB, context context.Context, query string, args []interface{}, destinationPtr interface{}) error {
|
||||||
|
|
||||||
if destinationPtr == nil {
|
if destinationPtr == nil {
|
||||||
return errors.New("jet: Destination is nil.")
|
return errors.New("jet: Destination is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
destinationPtrType := reflect.TypeOf(destinationPtr)
|
destinationPtrType := reflect.TypeOf(destinationPtr)
|
||||||
|
|
@ -142,23 +144,23 @@ func mapRowToSlice(scanContext *scanContext, groupKey string, slicePtrValue refl
|
||||||
structPtrValue := getSliceElemPtrAt(slicePtrValue, index)
|
structPtrValue := getSliceElemPtrAt(slicePtrValue, index)
|
||||||
|
|
||||||
return mapRowToStruct(scanContext, groupKey, structPtrValue, field, true)
|
return mapRowToStruct(scanContext, groupKey, structPtrValue, field, true)
|
||||||
} else {
|
}
|
||||||
destinationStructPtr := newElemPtrValueForSlice(slicePtrValue)
|
|
||||||
|
|
||||||
updated, err = mapRowToStruct(scanContext, groupKey, destinationStructPtr, field)
|
destinationStructPtr := newElemPtrValueForSlice(slicePtrValue)
|
||||||
|
|
||||||
|
updated, err = mapRowToStruct(scanContext, groupKey, destinationStructPtr, field)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if updated {
|
||||||
|
scanContext.uniqueDestObjectsMap[groupKey] = slicePtrValue.Elem().Len()
|
||||||
|
err = appendElemToSlice(slicePtrValue, destinationStructPtr)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if updated {
|
|
||||||
scanContext.uniqueDestObjectsMap[groupKey] = slicePtrValue.Elem().Len()
|
|
||||||
err = appendElemToSlice(slicePtrValue, destinationStructPtr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
@ -481,9 +483,8 @@ func valueToString(value reflect.Value) string {
|
||||||
if value.Kind() == reflect.Ptr {
|
if value.Kind() == reflect.Ptr {
|
||||||
if value.IsNil() {
|
if value.IsNil() {
|
||||||
return "nil"
|
return "nil"
|
||||||
} else {
|
|
||||||
valueInterface = value.Elem().Interface()
|
|
||||||
}
|
}
|
||||||
|
valueInterface = value.Elem().Interface()
|
||||||
} else {
|
} else {
|
||||||
valueInterface = value.Interface()
|
valueInterface = value.Interface()
|
||||||
}
|
}
|
||||||
|
|
@ -654,14 +655,14 @@ func (s *scanContext) getGroupKey(structType reflect.Type, structField *reflect.
|
||||||
}
|
}
|
||||||
|
|
||||||
if groupKeyInfo, ok := s.groupKeyInfoCache[mapKey]; ok {
|
if groupKeyInfo, ok := s.groupKeyInfoCache[mapKey]; ok {
|
||||||
return s.constructGroupKey(groupKeyInfo)
|
|
||||||
} else {
|
|
||||||
groupKeyInfo := s.getGroupKeyInfo(structType, structField)
|
|
||||||
|
|
||||||
s.groupKeyInfoCache[mapKey] = groupKeyInfo
|
|
||||||
|
|
||||||
return s.constructGroupKey(groupKeyInfo)
|
return s.constructGroupKey(groupKeyInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groupKeyInfo := s.getGroupKeyInfo(structType, structField)
|
||||||
|
|
||||||
|
s.groupKeyInfoCache[mapKey] = groupKeyInfo
|
||||||
|
|
||||||
|
return s.constructGroupKey(groupKeyInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanContext) constructGroupKey(groupKeyInfo groupKeyInfo) string {
|
func (s *scanContext) constructGroupKey(groupKeyInfo groupKeyInfo) string {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NullByteArray
|
// NullByteArray struct
|
||||||
type NullByteArray struct {
|
type NullByteArray struct {
|
||||||
ByteArray []byte
|
ByteArray []byte
|
||||||
Valid bool
|
Valid bool
|
||||||
|
|
@ -31,7 +31,7 @@ func (nb NullByteArray) Value() (driver.Value, error) {
|
||||||
return nb.ByteArray, nil
|
return nb.ByteArray, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//NullTime
|
// NullTime struct
|
||||||
type NullTime struct {
|
type NullTime struct {
|
||||||
Time time.Time
|
Time time.Time
|
||||||
Valid bool // Valid is true if Time is not NULL
|
Valid bool // Valid is true if Time is not NULL
|
||||||
|
|
@ -51,6 +51,7 @@ func (nt NullTime) Value() (driver.Value, error) {
|
||||||
return nt.Time, nil
|
return nt.Time, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NullInt32 struct
|
||||||
type NullInt32 struct {
|
type NullInt32 struct {
|
||||||
Int32 int32
|
Int32 int32
|
||||||
Valid bool // Valid is true if Int64 is not NULL
|
Valid bool // Valid is true if Int64 is not NULL
|
||||||
|
|
@ -83,6 +84,7 @@ func (n NullInt32) Value() (driver.Value, error) {
|
||||||
return n.Int32, nil
|
return n.Int32, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NullInt16 struct
|
||||||
type NullInt16 struct {
|
type NullInt16 struct {
|
||||||
Int16 int16
|
Int16 int16
|
||||||
Valid bool // Valid is true if Int64 is not NULL
|
Valid bool // Valid is true if Int64 is not NULL
|
||||||
|
|
@ -115,6 +117,7 @@ func (n NullInt16) Value() (driver.Value, error) {
|
||||||
return n.Int16, nil
|
return n.Int16, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NullFloat32 struct
|
||||||
type NullFloat32 struct {
|
type NullFloat32 struct {
|
||||||
Float32 float32
|
Float32 float32
|
||||||
Valid bool // Valid is true if Int64 is not NULL
|
Valid bool // Valid is true if Int64 is not NULL
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package metadata
|
package metadata
|
||||||
|
|
||||||
|
// MetaData interface
|
||||||
type MetaData interface {
|
type MetaData interface {
|
||||||
Name() string
|
Name() string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package postgres_metadata
|
package postgresmeta
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ColumnInfo metadata struct
|
||||||
type ColumnInfo struct {
|
type ColumnInfo struct {
|
||||||
Name string
|
Name string
|
||||||
IsNullable bool
|
IsNullable bool
|
||||||
|
|
@ -14,6 +15,7 @@ type ColumnInfo struct {
|
||||||
EnumName string
|
EnumName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SqlBuilderColumnType returns type of jet sql builder column
|
||||||
func (c ColumnInfo) SqlBuilderColumnType() string {
|
func (c ColumnInfo) SqlBuilderColumnType() string {
|
||||||
switch c.DataType {
|
switch c.DataType {
|
||||||
case "boolean":
|
case "boolean":
|
||||||
|
|
@ -41,6 +43,7 @@ func (c ColumnInfo) SqlBuilderColumnType() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GoBaseType returns model type for column info.
|
||||||
func (c ColumnInfo) GoBaseType() string {
|
func (c ColumnInfo) GoBaseType() string {
|
||||||
switch c.DataType {
|
switch c.DataType {
|
||||||
case "USER-DEFINED":
|
case "USER-DEFINED":
|
||||||
|
|
@ -72,6 +75,8 @@ func (c ColumnInfo) GoBaseType() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GoModelType returns model type for column info with optional pointer if
|
||||||
|
// column can be NULL.
|
||||||
func (c ColumnInfo) GoModelType() string {
|
func (c ColumnInfo) GoModelType() string {
|
||||||
typeStr := c.GoBaseType()
|
typeStr := c.GoBaseType()
|
||||||
if c.IsNullable {
|
if c.IsNullable {
|
||||||
|
|
@ -81,6 +86,7 @@ func (c ColumnInfo) GoModelType() string {
|
||||||
return typeStr
|
return typeStr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GoModelTag returns model field tag for column
|
||||||
func (c ColumnInfo) GoModelTag(isPrimaryKey bool) string {
|
func (c ColumnInfo) GoModelTag(isPrimaryKey bool) string {
|
||||||
tags := []string{}
|
tags := []string{}
|
||||||
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
package postgres_metadata
|
package postgresmeta
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"github.com/go-jet/jet/generator/internal/metadata"
|
"github.com/go-jet/jet/generator/internal/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EnumInfo struct
|
||||||
type EnumInfo struct {
|
type EnumInfo struct {
|
||||||
name string
|
name string
|
||||||
Values []string
|
Values []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns enum name
|
||||||
func (e EnumInfo) Name() string {
|
func (e EnumInfo) Name() string {
|
||||||
return e.name
|
return e.name
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
package postgres_metadata
|
package postgresmeta
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"github.com/go-jet/jet/generator/internal/metadata"
|
"github.com/go-jet/jet/generator/internal/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SchemaInfo metadata struct
|
||||||
type SchemaInfo struct {
|
type SchemaInfo struct {
|
||||||
DatabaseName string
|
DatabaseName string
|
||||||
Name string
|
Name string
|
||||||
|
|
@ -12,6 +13,7 @@ type SchemaInfo struct {
|
||||||
EnumInfos []metadata.MetaData
|
EnumInfos []metadata.MetaData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSchemaInfo returns schema information from db connection.
|
||||||
func GetSchemaInfo(db *sql.DB, databaseName, schemaName string) (schemaInfo SchemaInfo, err error) {
|
func GetSchemaInfo(db *sql.DB, databaseName, schemaName string) (schemaInfo SchemaInfo, err error) {
|
||||||
|
|
||||||
schemaInfo.DatabaseName = databaseName
|
schemaInfo.DatabaseName = databaseName
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
package postgres_metadata
|
package postgresmeta
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"github.com/go-jet/jet/internal/utils"
|
"github.com/go-jet/jet/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TableInfo metadata struct
|
||||||
type TableInfo struct {
|
type TableInfo struct {
|
||||||
SchemaName string
|
SchemaName string
|
||||||
name string
|
name string
|
||||||
|
|
@ -12,14 +13,17 @@ type TableInfo struct {
|
||||||
Columns []ColumnInfo
|
Columns []ColumnInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns table info name
|
||||||
func (t TableInfo) Name() string {
|
func (t TableInfo) Name() string {
|
||||||
return t.name
|
return t.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t TableInfo) IsPrimaryKey(columnName string) bool {
|
// IsPrimaryKey returns if column is a part of primary key
|
||||||
return t.PrimaryKeys[columnName]
|
func (t TableInfo) IsPrimaryKey(column string) bool {
|
||||||
|
return t.PrimaryKeys[column]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MutableColumns returns list of mutable columns for table
|
||||||
func (t TableInfo) MutableColumns() []ColumnInfo {
|
func (t TableInfo) MutableColumns() []ColumnInfo {
|
||||||
ret := []ColumnInfo{}
|
ret := []ColumnInfo{}
|
||||||
|
|
||||||
|
|
@ -34,6 +38,7 @@ func (t TableInfo) MutableColumns() []ColumnInfo {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetImports returns model imports for table.
|
||||||
func (t TableInfo) GetImports() []string {
|
func (t TableInfo) GetImports() []string {
|
||||||
imports := map[string]string{}
|
imports := map[string]string{}
|
||||||
|
|
||||||
|
|
@ -57,10 +62,12 @@ func (t TableInfo) GetImports() []string {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GoStructName returns go struct name for sql builder
|
||||||
func (t TableInfo) GoStructName() string {
|
func (t TableInfo) GoStructName() string {
|
||||||
return utils.ToGoIdentifier(t.name) + "Table"
|
return utils.ToGoIdentifier(t.name) + "Table"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTableInfo returns table info metadata
|
||||||
func GetTableInfo(db *sql.DB, dbName, schemaName, tableName string) (tableInfo TableInfo, err error) {
|
func GetTableInfo(db *sql.DB, dbName, schemaName, tableName string) (tableInfo TableInfo, err error) {
|
||||||
|
|
||||||
tableInfo.SchemaName = schemaName
|
tableInfo.SchemaName = schemaName
|
||||||
|
|
@ -4,13 +4,13 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-jet/jet/generator/internal/metadata"
|
"github.com/go-jet/jet/generator/internal/metadata"
|
||||||
"github.com/go-jet/jet/generator/internal/metadata/postgres-metadata"
|
"github.com/go-jet/jet/generator/internal/metadata/postgresmeta"
|
||||||
"github.com/go-jet/jet/internal/utils"
|
"github.com/go-jet/jet/internal/utils"
|
||||||
_ "github.com/lib/pq"
|
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DBConnection contains postgres connection details
|
||||||
type DBConnection struct {
|
type DBConnection struct {
|
||||||
Host string
|
Host string
|
||||||
Port string
|
Port string
|
||||||
|
|
@ -23,10 +23,11 @@ type DBConnection struct {
|
||||||
SchemaName string
|
SchemaName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Generate(destDir string, genData DBConnection) error {
|
// Generate generates jet files at destination dir from database connection details
|
||||||
|
func Generate(destDir string, dbConn DBConnection) error {
|
||||||
|
|
||||||
connectionString := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s %s",
|
connectionString := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s %s",
|
||||||
genData.Host, genData.Port, genData.User, genData.Password, genData.DBName, genData.SslMode, genData.Params)
|
dbConn.Host, dbConn.Port, dbConn.User, dbConn.Password, dbConn.DBName, dbConn.SslMode, dbConn.Params)
|
||||||
|
|
||||||
fmt.Println("Connecting to postgres database: " + connectionString)
|
fmt.Println("Connecting to postgres database: " + connectionString)
|
||||||
|
|
||||||
|
|
@ -43,7 +44,7 @@ func Generate(destDir string, genData DBConnection) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Retrieving schema information...")
|
fmt.Println("Retrieving schema information...")
|
||||||
schemaInfo, err := postgres_metadata.GetSchemaInfo(db, genData.DBName, genData.SchemaName)
|
schemaInfo, err := postgresmeta.GetSchemaInfo(db, dbConn.DBName, dbConn.SchemaName)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -55,7 +56,7 @@ func Generate(destDir string, genData DBConnection) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
schemaGenPath := path.Join(destDir, genData.DBName, genData.SchemaName)
|
schemaGenPath := path.Join(destDir, dbConn.DBName, dbConn.SchemaName)
|
||||||
fmt.Println("Destination directory:", schemaGenPath)
|
fmt.Println("Destination directory:", schemaGenPath)
|
||||||
fmt.Println("Cleaning up destination directory...")
|
fmt.Println("Cleaning up destination directory...")
|
||||||
err = utils.CleanUpGeneratedFiles(schemaGenPath)
|
err = utils.CleanUpGeneratedFiles(schemaGenPath)
|
||||||
|
|
@ -99,7 +100,7 @@ func Generate(destDir string, genData DBConnection) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generate(schemaInfo postgres_metadata.SchemaInfo, dirPath, packageName string, template string, metaDataList []metadata.MetaData) error {
|
func generate(schemaInfo postgresmeta.SchemaInfo, dirPath, packageName string, template string, metaDataList []metadata.MetaData) error {
|
||||||
modelDirPath := filepath.Join(dirPath, schemaInfo.DatabaseName, schemaInfo.Name, packageName)
|
modelDirPath := filepath.Join(dirPath, schemaInfo.DatabaseName, schemaInfo.Name, packageName)
|
||||||
|
|
||||||
err := utils.EnsureDirPath(modelDirPath)
|
err := utils.EnsureDirPath(modelDirPath)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ToGoIdentifier converts database to Go identifier.
|
||||||
func ToGoIdentifier(databaseIdentifier string) string {
|
func ToGoIdentifier(databaseIdentifier string) string {
|
||||||
if len(databaseIdentifier) == 0 {
|
if len(databaseIdentifier) == 0 {
|
||||||
return databaseIdentifier
|
return databaseIdentifier
|
||||||
|
|
@ -20,10 +21,12 @@ func ToGoIdentifier(databaseIdentifier string) string {
|
||||||
return snaker.SnakeToCamel(replaceInvalidChars(databaseIdentifier))
|
return snaker.SnakeToCamel(replaceInvalidChars(databaseIdentifier))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToGoFileName converts database identifier to Go file name.
|
||||||
func ToGoFileName(databaseIdentifier string) string {
|
func ToGoFileName(databaseIdentifier string) string {
|
||||||
return strings.ToLower(replaceInvalidChars(databaseIdentifier))
|
return strings.ToLower(replaceInvalidChars(databaseIdentifier))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveGoFile saves go file at folder dir, with name fileName and contents text.
|
||||||
func SaveGoFile(dirPath, fileName string, text []byte) error {
|
func SaveGoFile(dirPath, fileName string, text []byte) error {
|
||||||
newGoFilePath := filepath.Join(dirPath, fileName) + ".go"
|
newGoFilePath := filepath.Join(dirPath, fileName) + ".go"
|
||||||
|
|
||||||
|
|
@ -49,6 +52,7 @@ func SaveGoFile(dirPath, fileName string, text []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnsureDirPath ensures dir path exists. If path does not exist, creates new path.
|
||||||
func EnsureDirPath(dirPath string) error {
|
func EnsureDirPath(dirPath string) error {
|
||||||
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
|
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
|
||||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
err := os.MkdirAll(dirPath, os.ModePerm)
|
||||||
|
|
@ -61,6 +65,7 @@ func EnsureDirPath(dirPath string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateTemplate generates template with template text and template data.
|
||||||
func GenerateTemplate(templateText string, templateData interface{}) ([]byte, error) {
|
func GenerateTemplate(templateText string, templateData interface{}) ([]byte, error) {
|
||||||
|
|
||||||
t, err := template.New("sqlBuilderTableTemplate").Funcs(template.FuncMap{
|
t, err := template.New("sqlBuilderTableTemplate").Funcs(template.FuncMap{
|
||||||
|
|
@ -82,6 +87,7 @@ func GenerateTemplate(templateText string, templateData interface{}) ([]byte, er
|
||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CleanUpGeneratedFiles deletes everything at folder dir.
|
||||||
func CleanUpGeneratedFiles(dir string) error {
|
func CleanUpGeneratedFiles(dir string) error {
|
||||||
exist, err := DirExists(dir)
|
exist, err := DirExists(dir)
|
||||||
|
|
||||||
|
|
@ -100,6 +106,7 @@ func CleanUpGeneratedFiles(dir string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DirExists checks if folder at path exist.
|
||||||
func DirExists(path string) (bool, error) {
|
func DirExists(path string) (bool, error) {
|
||||||
_, err := os.Stat(path)
|
_, err := os.Stat(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
@ -118,8 +125,7 @@ func replaceInvalidChars(str string) string {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
// github.com/lib/pq
|
// FormatTimestamp formats t into Postgres' text format for timestamps. From: github.com/lib/pq
|
||||||
// FormatTimestamp formats t into Postgres' text format for timestamps.
|
|
||||||
func FormatTimestamp(t time.Time) []byte {
|
func FormatTimestamp(t time.Time) []byte {
|
||||||
// Need to send dates before 0001 A.D. with " BC" suffix, instead of the
|
// Need to send dates before 0001 A.D. with " BC" suffix, instead of the
|
||||||
// minus sign preferred by Go.
|
// minus sign preferred by Go.
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ func TestJoinEverything(t *testing.T) {
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, len(dest), 275)
|
assert.Equal(t, len(dest), 275)
|
||||||
assertJsonFile(t, "./testdata/joined_everything.json", dest)
|
assertJSONFile(t, "./testdata/joined_everything.json", dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSelfJoin(t *testing.T) {
|
func TestSelfJoin(t *testing.T) {
|
||||||
|
|
@ -146,7 +146,7 @@ ORDER BY "Employee"."EmployeeId";
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, len(dest), 8)
|
assert.Equal(t, len(dest), 8)
|
||||||
assertJson(t, dest[0:2], `
|
assertJSON(t, dest[0:2], `
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"EmployeeId": 1,
|
"EmployeeId": 1,
|
||||||
|
|
@ -285,7 +285,7 @@ func TestSubQueriesForQuotedNames(t *testing.T) {
|
||||||
LIMIT(10).
|
LIMIT(10).
|
||||||
AsTable("first10Artist")
|
AsTable("first10Artist")
|
||||||
|
|
||||||
artistId := Artist.ArtistId.From(first10Artist)
|
artistID := Artist.ArtistId.From(first10Artist)
|
||||||
|
|
||||||
first10Albums := Album.
|
first10Albums := Album.
|
||||||
SELECT(Album.AllColumns).
|
SELECT(Album.AllColumns).
|
||||||
|
|
@ -293,12 +293,12 @@ func TestSubQueriesForQuotedNames(t *testing.T) {
|
||||||
LIMIT(10).
|
LIMIT(10).
|
||||||
AsTable("first10Albums")
|
AsTable("first10Albums")
|
||||||
|
|
||||||
albumArtistId := Album.ArtistId.From(first10Albums)
|
albumArtistID := Album.ArtistId.From(first10Albums)
|
||||||
|
|
||||||
stmt := first10Artist.
|
stmt := first10Artist.
|
||||||
INNER_JOIN(first10Albums, artistId.EQ(albumArtistId)).
|
INNER_JOIN(first10Albums, artistID.EQ(albumArtistID)).
|
||||||
SELECT(first10Artist.AllColumns(), first10Albums.AllColumns()).
|
SELECT(first10Artist.AllColumns(), first10Albums.AllColumns()).
|
||||||
ORDER_BY(artistId)
|
ORDER_BY(artistID)
|
||||||
|
|
||||||
assertStatementSql(t, stmt, `
|
assertStatementSql(t, stmt, `
|
||||||
SELECT "first10Artist"."Artist.ArtistId" AS "Artist.ArtistId",
|
SELECT "first10Artist"."Artist.ArtistId" AS "Artist.ArtistId",
|
||||||
|
|
@ -337,26 +337,26 @@ ORDER BY "first10Artist"."Artist.ArtistId";
|
||||||
//spew.Dump(dest)
|
//spew.Dump(dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertJson(t *testing.T, data interface{}, expectedJson string) {
|
func assertJSON(t *testing.T, data interface{}, expectedJSON string) {
|
||||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, "\n"+string(jsonData)+"\n", expectedJson)
|
assert.Equal(t, "\n"+string(jsonData)+"\n", expectedJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertJsonFile(t *testing.T, jsonFilePath string, data interface{}) {
|
func assertJSONFile(t *testing.T, jsonFilePath string, data interface{}) {
|
||||||
fileJsonData, err := ioutil.ReadFile(jsonFilePath)
|
fileJSONData, err := ioutil.ReadFile(jsonFilePath)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
fileJsonData = bytes.Replace(fileJsonData, []byte("\r\n"), []byte("\n"), -1)
|
fileJSONData = bytes.Replace(fileJSONData, []byte("\r\n"), []byte("\n"), -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.Assert(t, string(fileJsonData) == string(jsonData))
|
assert.Assert(t, string(fileJSONData) == string(jsonData))
|
||||||
//assert.Equal(t, string(fileJsonData), string(jsonData))
|
//assert.Equal(t, string(fileJSONData), string(jsonData))
|
||||||
}
|
}
|
||||||
|
|
||||||
func jsonPrint(v interface{}) {
|
func jsonPrint(v interface{}) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package dbconfig
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
// test database connection parameters
|
||||||
const (
|
const (
|
||||||
Host = "localhost"
|
Host = "localhost"
|
||||||
Port = 5432
|
Port = 5432
|
||||||
|
|
@ -10,4 +11,5 @@ const (
|
||||||
DBName = "jetdb"
|
DBName = "jetdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ConnectString is PostgreSQL connection string
|
||||||
var ConnectString = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", Host, Port, User, Password, DBName)
|
var ConnectString = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", Host, Port, User, Password, DBName)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-jet/jet/generator/postgres"
|
"github.com/go-jet/jet/generator/postgres"
|
||||||
"github.com/go-jet/jet/tests/dbconfig"
|
"github.com/go-jet/jet/tests/dbconfig"
|
||||||
|
_ "github.com/lib/pq"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,5 +61,5 @@ func TestNorthwindJoinEverything(t *testing.T) {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
//jsonSave("./testdata/northwind-all.json", dest)
|
//jsonSave("./testdata/northwind-all.json", dest)
|
||||||
assertJsonFile(t, "./testdata/northwind-all.json", dest)
|
assertJSONFile(t, "./testdata/northwind-all.json", dest)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ FROM test_sample.person;
|
||||||
err := query.Query(db, &result)
|
err := query.Query(db, &result)
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assertJson(t, result, `
|
assertJSON(t, result, `
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6",
|
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6",
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ func TestScanToInvalidDestination(t *testing.T) {
|
||||||
t.Run("nil dest", func(t *testing.T) {
|
t.Run("nil dest", func(t *testing.T) {
|
||||||
err := query.Query(db, nil)
|
err := query.Query(db, nil)
|
||||||
|
|
||||||
assert.Error(t, err, "jet: Destination is nil.")
|
assert.Error(t, err, "jet: Destination is nil")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("struct dest", func(t *testing.T) {
|
t.Run("struct dest", func(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -532,7 +532,7 @@ ORDER BY city.city_id, address.address_id, customer.customer_id;
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, len(dest), 2)
|
assert.Equal(t, len(dest), 2)
|
||||||
assertJson(t, dest, `
|
assertJSON(t, dest, `
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"CityID": 312,
|
"CityID": 312,
|
||||||
|
|
@ -886,11 +886,11 @@ FROM dvds.actor
|
||||||
WHERE(Film.Rating.EQ(enum.MpaaRating.R)).
|
WHERE(Film.Rating.EQ(enum.MpaaRating.R)).
|
||||||
AsTable("rFilms")
|
AsTable("rFilms")
|
||||||
|
|
||||||
rFilmId := Film.FilmID.From(rRatingFilms)
|
rFilmID := Film.FilmID.From(rRatingFilms)
|
||||||
|
|
||||||
query := Actor.
|
query := Actor.
|
||||||
INNER_JOIN(FilmActor, Actor.ActorID.EQ(FilmActor.FilmID)).
|
INNER_JOIN(FilmActor, Actor.ActorID.EQ(FilmActor.FilmID)).
|
||||||
INNER_JOIN(rRatingFilms, FilmActor.FilmID.EQ(rFilmId)).
|
INNER_JOIN(rRatingFilms, FilmActor.FilmID.EQ(rFilmID)).
|
||||||
SELECT(
|
SELECT(
|
||||||
Actor.AllColumns,
|
Actor.AllColumns,
|
||||||
FilmActor.AllColumns,
|
FilmActor.AllColumns,
|
||||||
|
|
@ -1077,11 +1077,11 @@ ORDER BY customer_payment_sum."amount_sum" ASC;
|
||||||
GROUP_BY(Payment.CustomerID).
|
GROUP_BY(Payment.CustomerID).
|
||||||
AsTable("customer_payment_sum")
|
AsTable("customer_payment_sum")
|
||||||
|
|
||||||
customerId := Payment.CustomerID.From(customersPayments)
|
customerID := Payment.CustomerID.From(customersPayments)
|
||||||
amountSum := FloatColumn("amount_sum").From(customersPayments)
|
amountSum := FloatColumn("amount_sum").From(customersPayments)
|
||||||
|
|
||||||
query := Customer.
|
query := Customer.
|
||||||
INNER_JOIN(customersPayments, Customer.CustomerID.EQ(customerId)).
|
INNER_JOIN(customersPayments, Customer.CustomerID.EQ(customerID)).
|
||||||
SELECT(
|
SELECT(
|
||||||
Customer.AllColumns,
|
Customer.AllColumns,
|
||||||
amountSum.AS("CustomerWithAmounts.AmountSum"),
|
amountSum.AS("CustomerWithAmounts.AmountSum"),
|
||||||
|
|
@ -1123,7 +1123,7 @@ func TestSelectStaff(t *testing.T) {
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assertJson(t, staffs, `
|
assertJSON(t, staffs, `
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"StaffID": 1,
|
"StaffID": 1,
|
||||||
|
|
@ -1304,15 +1304,15 @@ LIMIT 20;
|
||||||
assertStatementSql(t, query, expectedQuery, int64(1), "ONE", int64(2), "TWO", int64(3), "THREE", "OTHER", int64(20))
|
assertStatementSql(t, query, expectedQuery, int64(1), "ONE", int64(2), "TWO", int64(3), "THREE", "OTHER", int64(20))
|
||||||
|
|
||||||
dest := []struct {
|
dest := []struct {
|
||||||
StaffIdNum string
|
StaffIDNum string
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
err := query.Query(db, &dest)
|
err := query.Query(db, &dest)
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, len(dest), 20)
|
assert.Equal(t, len(dest), 20)
|
||||||
assert.Equal(t, dest[0].StaffIdNum, "TWO")
|
assert.Equal(t, dest[0].StaffIDNum, "TWO")
|
||||||
assert.Equal(t, dest[1].StaffIdNum, "ONE")
|
assert.Equal(t, dest[1].StaffIDNum, "ONE")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLockTable(t *testing.T) {
|
func TestLockTable(t *testing.T) {
|
||||||
|
|
@ -1506,7 +1506,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
//jsonSave("./testdata/quick-start-dest.json", dest)
|
//jsonSave("./testdata/quick-start-dest.json", dest)
|
||||||
assertJsonFile(t, "./testdata/quick-start-dest.json", dest)
|
assertJSONFile(t, "./testdata/quick-start-dest.json", dest)
|
||||||
|
|
||||||
var dest2 []struct {
|
var dest2 []struct {
|
||||||
model.Category
|
model.Category
|
||||||
|
|
@ -1519,7 +1519,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
//jsonSave("./testdata/quick-start-dest2.json", dest2)
|
//jsonSave("./testdata/quick-start-dest2.json", dest2)
|
||||||
assertJsonFile(t, "./testdata/quick-start-dest2.json", dest2)
|
assertJSONFile(t, "./testdata/quick-start-dest2.json", dest2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQuickStartWithSubQueries(t *testing.T) {
|
func TestQuickStartWithSubQueries(t *testing.T) {
|
||||||
|
|
@ -1529,22 +1529,22 @@ func TestQuickStartWithSubQueries(t *testing.T) {
|
||||||
WHERE(Film.Length.GT(Int(180))).
|
WHERE(Film.Length.GT(Int(180))).
|
||||||
AsTable("films")
|
AsTable("films")
|
||||||
|
|
||||||
filmId := Film.FilmID.From(filmLogerThan180)
|
filmID := Film.FilmID.From(filmLogerThan180)
|
||||||
filmLanguageId := Film.LanguageID.From(filmLogerThan180)
|
filmLanguageID := Film.LanguageID.From(filmLogerThan180)
|
||||||
|
|
||||||
categoriesNotAction := Category.
|
categoriesNotAction := Category.
|
||||||
SELECT(Category.AllColumns).
|
SELECT(Category.AllColumns).
|
||||||
WHERE(Category.Name.NOT_EQ(String("Action"))).
|
WHERE(Category.Name.NOT_EQ(String("Action"))).
|
||||||
AsTable("categories")
|
AsTable("categories")
|
||||||
|
|
||||||
categoryId := Category.CategoryID.From(categoriesNotAction)
|
categoryID := Category.CategoryID.From(categoriesNotAction)
|
||||||
|
|
||||||
stmt := Actor.
|
stmt := Actor.
|
||||||
INNER_JOIN(FilmActor, Actor.ActorID.EQ(FilmActor.ActorID)).
|
INNER_JOIN(FilmActor, Actor.ActorID.EQ(FilmActor.ActorID)).
|
||||||
INNER_JOIN(filmLogerThan180, filmId.EQ(FilmActor.FilmID)).
|
INNER_JOIN(filmLogerThan180, filmID.EQ(FilmActor.FilmID)).
|
||||||
INNER_JOIN(Language, Language.LanguageID.EQ(filmLanguageId)).
|
INNER_JOIN(Language, Language.LanguageID.EQ(filmLanguageID)).
|
||||||
INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(filmId)).
|
INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(filmID)).
|
||||||
INNER_JOIN(categoriesNotAction, categoryId.EQ(FilmCategory.CategoryID)).
|
INNER_JOIN(categoriesNotAction, categoryID.EQ(FilmCategory.CategoryID)).
|
||||||
SELECT(
|
SELECT(
|
||||||
Actor.AllColumns,
|
Actor.AllColumns,
|
||||||
filmLogerThan180.AllColumns(),
|
filmLogerThan180.AllColumns(),
|
||||||
|
|
@ -1552,7 +1552,7 @@ func TestQuickStartWithSubQueries(t *testing.T) {
|
||||||
categoriesNotAction.AllColumns(),
|
categoriesNotAction.AllColumns(),
|
||||||
).ORDER_BY(
|
).ORDER_BY(
|
||||||
Actor.ActorID.ASC(),
|
Actor.ActorID.ASC(),
|
||||||
filmId.ASC(),
|
filmID.ASC(),
|
||||||
)
|
)
|
||||||
|
|
||||||
var dest []struct {
|
var dest []struct {
|
||||||
|
|
@ -1571,7 +1571,7 @@ func TestQuickStartWithSubQueries(t *testing.T) {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
//jsonSave("./testdata/quick-start-dest.json", dest)
|
//jsonSave("./testdata/quick-start-dest.json", dest)
|
||||||
assertJsonFile(t, "./testdata/quick-start-dest.json", dest)
|
assertJSONFile(t, "./testdata/quick-start-dest.json", dest)
|
||||||
|
|
||||||
var dest2 []struct {
|
var dest2 []struct {
|
||||||
model.Category
|
model.Category
|
||||||
|
|
@ -1584,5 +1584,5 @@ func TestQuickStartWithSubQueries(t *testing.T) {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
//jsonSave("./testdata/quick-start-dest2.json", dest2)
|
//jsonSave("./testdata/quick-start-dest2.json", dest2)
|
||||||
assertJsonFile(t, "./testdata/quick-start-dest2.json", dest2)
|
assertJSONFile(t, "./testdata/quick-start-dest2.json", dest2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue