MySQL execution and scan support.
This commit is contained in:
parent
5dda5e1e11
commit
bffa102849
34 changed files with 48216 additions and 337 deletions
|
|
@ -93,7 +93,7 @@ Usage of jet:
|
|||
|
||||
err = postgres.Generate(destDir, genData)
|
||||
|
||||
case jet.MySql.Name:
|
||||
case jet.MySQL.Name:
|
||||
if host == "" || port == 0 || user == "" || dbName == "" {
|
||||
fmt.Println("\njet: required flag missing")
|
||||
flag.Usage()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
var (
|
||||
PostgreSQL = newPostgresDialect()
|
||||
MySql = newMySQLDialect()
|
||||
MySQL = newMySQLDialect()
|
||||
)
|
||||
|
||||
func newPostgresDialect() Dialect {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import (
|
|||
"fmt"
|
||||
"github.com/go-jet/jet/execution/internal"
|
||||
"github.com/go-jet/jet/internal/utils"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/google/uuid"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -126,7 +128,7 @@ func mapRowToSlice(scanContext *scanContext, groupKey string, slicePtrValue refl
|
|||
|
||||
sliceElemType := getSliceElemType(slicePtrValue)
|
||||
|
||||
if isGoBaseType(sliceElemType) {
|
||||
if isSimpleModelType(sliceElemType) {
|
||||
updated, err = mapRowToBaseTypeSlice(scanContext, slicePtrValue, field)
|
||||
return
|
||||
}
|
||||
|
|
@ -226,7 +228,7 @@ func (s *scanContext) getTypeInfo(structType reflect.Type, parentField *reflect.
|
|||
|
||||
if implementsScannerType(field.Type) {
|
||||
fieldMap.implementsScanner = true
|
||||
} else if !isGoBaseType(field.Type) {
|
||||
} else if !isSimpleModelType(field.Type) {
|
||||
fieldMap.complexType = true
|
||||
}
|
||||
|
||||
|
|
@ -497,12 +499,34 @@ func valueToString(value reflect.Value) string {
|
|||
return fmt.Sprintf("%#v", valueInterface)
|
||||
}
|
||||
|
||||
func isGoBaseType(objType reflect.Type) bool {
|
||||
typeStr := objType.String()
|
||||
var timeType = reflect.TypeOf(time.Now())
|
||||
var uuidType = reflect.TypeOf(uuid.New())
|
||||
|
||||
switch typeStr {
|
||||
case "string", "int", "int16", "int32", "int64", "float32", "float64", "time.Time", "bool", "[]byte", "[]uint8",
|
||||
"*string", "*int", "*int16", "*int32", "*int64", "*float32", "*float64", "*time.Time", "*bool", "*[]byte", "*[]uint8":
|
||||
func isSimpleModelType(objType reflect.Type) bool {
|
||||
objType = indirectType(objType)
|
||||
|
||||
switch objType.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64,
|
||||
reflect.String,
|
||||
reflect.Bool:
|
||||
return true
|
||||
case reflect.Slice:
|
||||
return objType.Elem().Kind() == reflect.Uint8 //[]byte
|
||||
case reflect.Struct:
|
||||
return objType == timeType || objType == uuidType // time.Time || uuid.UUID
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func tryAssign(source, destination reflect.Value) bool {
|
||||
if source.Type().ConvertibleTo(destination.Type()) {
|
||||
source = source.Convert(destination.Type())
|
||||
}
|
||||
if source.Type().AssignableTo(destination.Type()) {
|
||||
destination.Set(source)
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -510,35 +534,50 @@ func isGoBaseType(objType reflect.Type) bool {
|
|||
}
|
||||
|
||||
func setReflectValue(source, destination reflect.Value) error {
|
||||
var sourceElem reflect.Value
|
||||
|
||||
if tryAssign(source, destination) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if destination.Kind() == reflect.Ptr {
|
||||
if source.Kind() == reflect.Ptr {
|
||||
sourceElem = source
|
||||
|
||||
if !source.IsNil() {
|
||||
if destination.IsNil() {
|
||||
initializeValueIfNilPtr(destination)
|
||||
}
|
||||
|
||||
tryAssign(source.Elem(), destination.Elem())
|
||||
}
|
||||
} else {
|
||||
if source.CanAddr() {
|
||||
sourceElem = source.Addr()
|
||||
source = source.Addr()
|
||||
} else {
|
||||
sourceCopy := reflect.New(source.Type())
|
||||
sourceCopy.Elem().Set(source)
|
||||
|
||||
sourceElem = sourceCopy
|
||||
source = sourceCopy
|
||||
}
|
||||
|
||||
if tryAssign(source, destination) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if tryAssign(source.Elem(), destination.Elem()) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if source.Kind() == reflect.Ptr {
|
||||
sourceElem = source.Elem()
|
||||
} else {
|
||||
sourceElem = source
|
||||
}
|
||||
source = source.Elem()
|
||||
}
|
||||
|
||||
if !sourceElem.Type().AssignableTo(destination.Type()) {
|
||||
return errors.New("jet: can't set " + sourceElem.Type().String() + " to " + destination.Type().String())
|
||||
}
|
||||
|
||||
destination.Set(sourceElem)
|
||||
|
||||
if tryAssign(source, destination) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("jet: can't set " + source.Type().String() + " to " + destination.Type().String())
|
||||
}
|
||||
|
||||
func createScanValue(columnTypes []*sql.ColumnType) []interface{} {
|
||||
|
|
@ -555,33 +594,63 @@ func createScanValue(columnTypes []*sql.ColumnType) []interface{} {
|
|||
return values
|
||||
}
|
||||
|
||||
var nullFloatType = reflect.TypeOf(internal.NullFloat32{})
|
||||
var nullFloat64Type = reflect.TypeOf(sql.NullFloat64{})
|
||||
var int8Type = reflect.TypeOf(int8(1))
|
||||
var unit8Type = reflect.TypeOf(uint8(1))
|
||||
var int16Type = reflect.TypeOf(int16(1))
|
||||
var uint16Type = reflect.TypeOf(uint16(1))
|
||||
var int32Type = reflect.TypeOf(int32(1))
|
||||
var uint32Type = reflect.TypeOf(uint32(1))
|
||||
var int64Type = reflect.TypeOf(int64(1))
|
||||
var uint64Type = reflect.TypeOf(uint64(1))
|
||||
var float32Type = reflect.TypeOf(float32(1.1))
|
||||
var float64Type = reflect.TypeOf(float64(1.1))
|
||||
|
||||
var nullInt8Type = reflect.TypeOf(internal.NullInt8{})
|
||||
var nullUInt8Type = reflect.TypeOf(internal.NullUInt8{})
|
||||
var nullInt16Type = reflect.TypeOf(internal.NullInt16{})
|
||||
var nullUInt16Type = reflect.TypeOf(internal.NullUInt16{})
|
||||
var nullInt32Type = reflect.TypeOf(internal.NullInt32{})
|
||||
var nullUInt32Type = reflect.TypeOf(internal.NullUInt32{})
|
||||
var nullInt64Type = reflect.TypeOf(sql.NullInt64{})
|
||||
var nullUInt64Type = reflect.TypeOf(internal.NullUInt64{})
|
||||
|
||||
var nullFloat32Type = reflect.TypeOf(internal.NullFloat32{})
|
||||
var nullFloat64Type = reflect.TypeOf(sql.NullFloat64{})
|
||||
|
||||
var nullStringType = reflect.TypeOf(sql.NullString{})
|
||||
|
||||
var nullBoolType = reflect.TypeOf(sql.NullBool{})
|
||||
|
||||
var nullTimeType = reflect.TypeOf(internal.NullTime{})
|
||||
var mySQLNullTime = reflect.TypeOf(mysql.NullTime{})
|
||||
|
||||
var nullByteArrayType = reflect.TypeOf(internal.NullByteArray{})
|
||||
|
||||
func newScanType(columnType *sql.ColumnType) reflect.Type {
|
||||
|
||||
switch columnType.ScanType() {
|
||||
case mySQLNullTime:
|
||||
return mySQLNullTime
|
||||
}
|
||||
|
||||
switch columnType.DatabaseTypeName() {
|
||||
case "INT2":
|
||||
case "TINYINT":
|
||||
return nullInt8Type
|
||||
case "INT2", "SMALLINT", "YEAR":
|
||||
return nullInt16Type
|
||||
case "INT4":
|
||||
case "INT4", "MEDIUMINT", "INT":
|
||||
return nullInt32Type
|
||||
case "INT8":
|
||||
case "INT8", "BIGINT":
|
||||
return nullInt64Type
|
||||
case "VARCHAR", "TEXT", "", "_TEXT", "TSVECTOR", "BPCHAR", "UUID", "JSON", "JSONB", "INTERVAL", "POINT", "BIT", "VARBIT", "XML":
|
||||
case "CHAR", "VARCHAR", "TEXT", "", "_TEXT", "TSVECTOR", "BPCHAR", "UUID", "JSON", "JSONB", "INTERVAL", "POINT", "BIT", "VARBIT", "XML":
|
||||
return nullStringType
|
||||
case "FLOAT4":
|
||||
return nullFloatType
|
||||
case "FLOAT8", "NUMERIC", "DECIMAL":
|
||||
return nullFloat32Type
|
||||
case "FLOAT8", "NUMERIC", "DECIMAL", "FLOAT", "DOUBLE":
|
||||
return nullFloat64Type
|
||||
case "BOOL":
|
||||
return nullBoolType
|
||||
case "BYTEA":
|
||||
case "BYTEA", "BINARY", "VARBINARY", "BLOB":
|
||||
return nullByteArrayType
|
||||
case "DATE", "TIMESTAMP", "TIMESTAMPTZ", "TIME", "TIMETZ":
|
||||
return nullTimeType
|
||||
|
|
@ -697,7 +766,7 @@ func (s *scanContext) getGroupKeyInfo(structType reflect.Type, parentField *refl
|
|||
field := structType.Field(i)
|
||||
newTypeName, fieldName := getTypeAndFieldName(typeName, field)
|
||||
|
||||
if !isGoBaseType(field.Type) {
|
||||
if !isSimpleModelType(field.Type) {
|
||||
var structType reflect.Type
|
||||
if field.Type.Kind() == reflect.Struct {
|
||||
structType = field.Type
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@ package internal
|
|||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullByteArray struct
|
||||
type NullByteArray struct {
|
||||
ByteArray []byte
|
||||
|
|
@ -31,6 +34,8 @@ func (nb NullByteArray) Value() (driver.Value, error) {
|
|||
return nb.ByteArray, nil
|
||||
}
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullTime struct
|
||||
type NullTime struct {
|
||||
Time time.Time
|
||||
|
|
@ -51,25 +56,31 @@ func (nt NullTime) Value() (driver.Value, error) {
|
|||
return nt.Time, nil
|
||||
}
|
||||
|
||||
// NullInt32 struct
|
||||
type NullInt32 struct {
|
||||
Int32 int32
|
||||
Valid bool // Valid is true if Int64 is not NULL
|
||||
//===============================================================//
|
||||
|
||||
// NullInt8 struct
|
||||
type NullInt8 struct {
|
||||
Int8 int8
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullInt32) Scan(value interface{}) error {
|
||||
func (n *NullInt8) Scan(value interface{}) error {
|
||||
|
||||
switch v := value.(type) {
|
||||
case int64:
|
||||
n.Int32, n.Valid = int32(v), true
|
||||
n.Int8, n.Valid = int8(v), true
|
||||
return nil
|
||||
case int32:
|
||||
n.Int32, n.Valid = v, true
|
||||
case int8:
|
||||
n.Int8, n.Valid = v, true
|
||||
return nil
|
||||
case uint8:
|
||||
n.Int32, n.Valid = int32(v), true
|
||||
case []byte:
|
||||
intV, err := strconv.ParseInt(string(v), 10, 8)
|
||||
if err == nil {
|
||||
n.Int8, n.Valid = int8(intV), true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
n.Valid = false
|
||||
|
||||
|
|
@ -77,21 +88,60 @@ func (n *NullInt32) Scan(value interface{}) error {
|
|||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullInt32) Value() (driver.Value, error) {
|
||||
func (n NullInt8) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return n.Int32, nil
|
||||
return n.Int8, nil
|
||||
}
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullUInt8 struct
|
||||
type NullUInt8 struct {
|
||||
Uint8 uint8
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullUInt8) Scan(value interface{}) error {
|
||||
|
||||
switch v := value.(type) {
|
||||
case uint8:
|
||||
n.Uint8, n.Valid = v, true
|
||||
return nil
|
||||
case []byte:
|
||||
intV, err := strconv.ParseInt(string(v), 10, 8)
|
||||
if err == nil {
|
||||
n.Uint8, n.Valid = uint8(intV), true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
n.Valid = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullUInt8) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return n.Uint8, nil
|
||||
}
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullInt16 struct
|
||||
type NullInt16 struct {
|
||||
Int16 int16
|
||||
Valid bool // Valid is true if Int64 is not NULL
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullInt16) Scan(value interface{}) error {
|
||||
|
||||
switch v := value.(type) {
|
||||
case int64:
|
||||
n.Int16, n.Valid = int16(v), true
|
||||
|
|
@ -99,9 +149,18 @@ func (n *NullInt16) Scan(value interface{}) error {
|
|||
case int16:
|
||||
n.Int16, n.Valid = v, true
|
||||
return nil
|
||||
case int8:
|
||||
n.Int16, n.Valid = int16(v), true
|
||||
return nil
|
||||
case uint8:
|
||||
n.Int16, n.Valid = int16(v), true
|
||||
return nil
|
||||
case []byte:
|
||||
intV, err := strconv.ParseInt(string(v), 10, 16)
|
||||
if err == nil {
|
||||
n.Int16, n.Valid = int16(intV), true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
n.Valid = false
|
||||
|
|
@ -117,10 +176,259 @@ func (n NullInt16) Value() (driver.Value, error) {
|
|||
return n.Int16, nil
|
||||
}
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullUInt16 struct
|
||||
type NullUInt16 struct {
|
||||
UInt16 uint16
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullUInt16) Scan(value interface{}) error {
|
||||
|
||||
switch v := value.(type) {
|
||||
case uint16:
|
||||
n.UInt16, n.Valid = v, true
|
||||
return nil
|
||||
case int8:
|
||||
n.UInt16, n.Valid = uint16(v), true
|
||||
return nil
|
||||
case uint8:
|
||||
n.UInt16, n.Valid = uint16(v), true
|
||||
return nil
|
||||
case []byte:
|
||||
intV, err := strconv.ParseInt(string(v), 10, 16)
|
||||
if err == nil {
|
||||
n.UInt16, n.Valid = uint16(intV), true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
n.Valid = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullUInt16) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return n.UInt16, nil
|
||||
}
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullInt32 struct
|
||||
type NullInt32 struct {
|
||||
Int32 int32
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullInt32) Scan(value interface{}) error {
|
||||
|
||||
switch v := value.(type) {
|
||||
case int64:
|
||||
n.Int32, n.Valid = int32(v), true
|
||||
return nil
|
||||
case int32:
|
||||
n.Int32, n.Valid = v, true
|
||||
return nil
|
||||
case int16:
|
||||
n.Int32, n.Valid = int32(v), true
|
||||
return nil
|
||||
case uint16:
|
||||
n.Int32, n.Valid = int32(v), true
|
||||
return nil
|
||||
case int8:
|
||||
n.Int32, n.Valid = int32(v), true
|
||||
return nil
|
||||
case uint8:
|
||||
n.Int32, n.Valid = int32(v), true
|
||||
return nil
|
||||
case []byte:
|
||||
intV, err := strconv.ParseInt(string(v), 10, 32)
|
||||
if err == nil {
|
||||
n.Int32, n.Valid = int32(intV), true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
n.Valid = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullInt32) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return n.Int32, nil
|
||||
}
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullInt32 struct
|
||||
type NullUInt32 struct {
|
||||
UInt32 uint32
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullUInt32) Scan(value interface{}) error {
|
||||
|
||||
switch v := value.(type) {
|
||||
case uint32:
|
||||
n.UInt32, n.Valid = v, true
|
||||
return nil
|
||||
case int16:
|
||||
n.UInt32, n.Valid = uint32(v), true
|
||||
return nil
|
||||
case uint16:
|
||||
n.UInt32, n.Valid = uint32(v), true
|
||||
return nil
|
||||
case int8:
|
||||
n.UInt32, n.Valid = uint32(v), true
|
||||
return nil
|
||||
case uint8:
|
||||
n.UInt32, n.Valid = uint32(v), true
|
||||
return nil
|
||||
case []byte:
|
||||
intV, err := strconv.ParseInt(string(v), 10, 32)
|
||||
if err == nil {
|
||||
n.UInt32, n.Valid = uint32(intV), true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
n.Valid = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullUInt32) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return n.UInt32, nil
|
||||
}
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullInt32 struct
|
||||
type NullInt64 struct {
|
||||
Int64 int64
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullInt64) Scan(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case int64:
|
||||
n.Int64, n.Valid = v, true
|
||||
return nil
|
||||
case int32:
|
||||
n.Int64, n.Valid = int64(v), true
|
||||
return nil
|
||||
case uint32:
|
||||
n.Int64, n.Valid = int64(v), true
|
||||
return nil
|
||||
case int16:
|
||||
n.Int64, n.Valid = int64(v), true
|
||||
return nil
|
||||
case uint16:
|
||||
n.Int64, n.Valid = int64(v), true
|
||||
return nil
|
||||
case int8:
|
||||
n.Int64, n.Valid = int64(v), true
|
||||
return nil
|
||||
case uint8:
|
||||
n.Int64, n.Valid = int64(v), true
|
||||
return nil
|
||||
case []byte:
|
||||
intV, err := strconv.ParseInt(string(v), 10, 32)
|
||||
if err == nil {
|
||||
n.Int64, n.Valid = int64(intV), true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
n.Valid = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullInt64) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return n.Int64, nil
|
||||
}
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullInt32 struct
|
||||
type NullUInt64 struct {
|
||||
UInt64 uint64
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (n *NullUInt64) Scan(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case uint64:
|
||||
n.UInt64, n.Valid = v, true
|
||||
return nil
|
||||
case int32:
|
||||
n.UInt64, n.Valid = uint64(v), true
|
||||
return nil
|
||||
case uint32:
|
||||
n.UInt64, n.Valid = uint64(v), true
|
||||
return nil
|
||||
case int16:
|
||||
n.UInt64, n.Valid = uint64(v), true
|
||||
return nil
|
||||
case uint16:
|
||||
n.UInt64, n.Valid = uint64(v), true
|
||||
return nil
|
||||
case int8:
|
||||
n.UInt64, n.Valid = uint64(v), true
|
||||
return nil
|
||||
case uint8:
|
||||
n.UInt64, n.Valid = uint64(v), true
|
||||
return nil
|
||||
case []byte:
|
||||
intV, err := strconv.ParseInt(string(v), 10, 32)
|
||||
if err == nil {
|
||||
n.UInt64, n.Valid = uint64(intV), true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
n.Valid = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (n NullUInt64) Value() (driver.Value, error) {
|
||||
if !n.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return n.UInt64, nil
|
||||
}
|
||||
|
||||
//===============================================================//
|
||||
|
||||
// NullFloat32 struct
|
||||
type NullFloat32 struct {
|
||||
Float32 float32
|
||||
Valid bool // Valid is true if Int64 is not NULL
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ func (c ColumnInfo) SqlBuilderColumnType() string {
|
|||
case "date":
|
||||
return "Date"
|
||||
case "timestamp without time zone",
|
||||
"timestamp": //MySQL:
|
||||
"timestamp", "datetime": //MySQL:
|
||||
return "Timestamp"
|
||||
case "timestamp with time zone":
|
||||
return "Timestampz"
|
||||
|
|
@ -40,7 +40,8 @@ func (c ColumnInfo) SqlBuilderColumnType() string {
|
|||
"char", "varchar", "binary", "varbinary",
|
||||
"tinyblob", "blob", "mediumblob", "longblob", "tinytext", "mediumtext", "longtext": // MySQL
|
||||
return "String"
|
||||
case "real", "numeric", "decimal", "double precision", "float":
|
||||
case "real", "numeric", "decimal", "double precision", "float",
|
||||
"double": // MySQL
|
||||
return "Float"
|
||||
default:
|
||||
fmt.Println("Unsupported sql type: " + c.DataType + ", using string column instead for sql builder.")
|
||||
|
|
@ -66,18 +67,19 @@ func (c ColumnInfo) GoBaseType() string {
|
|||
case "bigint":
|
||||
return "int64"
|
||||
case "date", "timestamp without time zone", "timestamp with time zone", "time with time zone", "time without time zone",
|
||||
"timestamp": // MySQL
|
||||
"timestamp", "datetime": // MySQL
|
||||
return "time.Time"
|
||||
case "bytea",
|
||||
"tinyblob", "blob", "mediumblob", "longblob": //MySQL
|
||||
"binary", "varbinary", "tinyblob", "blob", "mediumblob", "longblob": //MySQL
|
||||
return "[]byte"
|
||||
case "text", "character", "character varying", "tsvector", "bit", "bit varying", "money", "json", "jsonb",
|
||||
"xml", "point", "interval", "line", "ARRAY",
|
||||
"char", "varchar", "binary", "varbinary", "tinytext", "mediumtext", "longtext": // MySQL
|
||||
"char", "varchar", "tinytext", "mediumtext", "longtext": // MySQL
|
||||
return "string"
|
||||
case "real":
|
||||
return "float32"
|
||||
case "numeric", "decimal", "double precision":
|
||||
case "numeric", "decimal", "double precision", "float",
|
||||
"double": // MySQL
|
||||
return "float64"
|
||||
case "uuid":
|
||||
return "uuid.UUID"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package metadata
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -122,8 +121,6 @@ func (m *MySqlQuerySet) GetEnumsMetaData(db *sql.DB, schemaName string) ([]MetaD
|
|||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println(enumValues)
|
||||
|
||||
enumValues = strings.Replace(enumValues[1:len(enumValues)-1], "'", "", -1)
|
||||
|
||||
ret = append(ret, EnumInfo{
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ func GetSchemaInfo(db *sql.DB, schemaName string, querySet MetaDataQuerySet) (sc
|
|||
|
||||
func getTableInfos(db *sql.DB, querySet MetaDataQuerySet, schemaName string) ([]MetaData, error) {
|
||||
|
||||
fmt.Println(querySet.ListOfTablesQuery())
|
||||
|
||||
rows, err := db.Query(querySet.ListOfTablesQuery(), schemaName)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -51,8 +49,6 @@ func getTableInfos(db *sql.DB, querySet MetaDataQuerySet, schemaName string) ([]
|
|||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println(tableName)
|
||||
|
||||
tableInfo, err := GetTableInfo(db, querySet, schemaName, tableName)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ func Generate(destDir string, dbConn DBConnection) error {
|
|||
|
||||
genPath := path.Join(destDir, dbConn.DBName)
|
||||
|
||||
err = template.GenerateFiles(genPath, dbInfo.TableInfos, dbInfo.EnumInfos, jet.MySql)
|
||||
err = template.GenerateFiles(genPath, dbInfo.TableInfos, dbInfo.EnumInfos, jet.MySQL)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
80
internal/testutils/test_utils.go
Normal file
80
internal/testutils/test_utils.go
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
package testutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/go-jet/jet"
|
||||
"gotest.tools/assert"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func JsonPrint(v interface{}) {
|
||||
jsonText, _ := json.MarshalIndent(v, "", "\t")
|
||||
fmt.Println(string(jsonText))
|
||||
}
|
||||
|
||||
func JsonSave(path string, v interface{}) {
|
||||
jsonText, _ := json.MarshalIndent(v, "", "\t")
|
||||
|
||||
err := ioutil.WriteFile(path, jsonText, 0644)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func AssertJSON(t *testing.T, data interface{}, expectedJSON string) {
|
||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, "\n"+string(jsonData)+"\n", expectedJSON)
|
||||
}
|
||||
|
||||
func AssertJSONFile(t *testing.T, jsonFilePath string, data interface{}) {
|
||||
fileJSONData, err := ioutil.ReadFile(jsonFilePath)
|
||||
assert.NilError(t, err)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
fileJSONData = bytes.Replace(fileJSONData, []byte("\r\n"), []byte("\n"), -1)
|
||||
}
|
||||
|
||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Assert(t, string(fileJSONData) == string(jsonData))
|
||||
//assert.Equal(t, string(fileJSONData), string(jsonData))
|
||||
}
|
||||
|
||||
func AssertStatementSql(t *testing.T, query jet.Statement, expectedQuery string, expectedArgs ...interface{}) {
|
||||
_, args, err := query.Sql()
|
||||
assert.NilError(t, err)
|
||||
//assert.Equal(t, queryStr, expectedQuery)
|
||||
assert.DeepEqual(t, args, expectedArgs)
|
||||
|
||||
debuqSql, err := query.DebugSql()
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, debuqSql, expectedQuery)
|
||||
}
|
||||
|
||||
func TimestampWithoutTimeZone(t string, precision int) *time.Time {
|
||||
|
||||
precisionStr := ""
|
||||
|
||||
if precision > 0 {
|
||||
precisionStr = "." + strings.Repeat("9", precision)
|
||||
}
|
||||
|
||||
newTime, err := time.Parse("2006-01-02 15:04:05"+precisionStr+" +0000", t+" +0000")
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &newTime
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package tests
|
|||
|
||||
import (
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"github.com/google/uuid"
|
||||
|
|
@ -464,8 +465,8 @@ func TestSubQueryColumnReference(t *testing.T) {
|
|||
)
|
||||
) AS "subQuery"`
|
||||
|
||||
subQueries[selectSubQuery] = expected{sql: selectexpectedSQL, args: []interface{}{int64(2)}}
|
||||
subQueries[unionSubQuery] = expected{sql: unionexpectedSQL, args: []interface{}{int64(1), int64(1), int64(1)}}
|
||||
subQueries[selectSubQuery] = expected{sql: selectexpectedSQL, args: []interface{}{int64(2)}}
|
||||
|
||||
for subQuery, expected := range subQueries {
|
||||
boolColumn := AllTypes.Boolean.From(subQuery)
|
||||
|
|
@ -506,7 +507,7 @@ SELECT "subQuery"."all_types.boolean" AS "all_types.boolean",
|
|||
"subQuery"."aliasedColumn" AS "aliasedColumn"
|
||||
FROM`
|
||||
|
||||
assertStatementSql(t, stmt1, expectedSQL+expected.sql+";\n", expected.args...)
|
||||
testutils.AssertStatementSql(t, stmt1, expectedSQL+expected.sql+";\n", expected.args...)
|
||||
|
||||
dest1 := []model.AllTypes{}
|
||||
err := stmt1.Query(db, &dest1)
|
||||
|
|
@ -529,7 +530,7 @@ FROM`
|
|||
|
||||
//fmt.Println(stmt2.DebugSql())
|
||||
|
||||
assertStatementSql(t, stmt2, expectedSQL+expected.sql+";\n", expected.args...)
|
||||
testutils.AssertStatementSql(t, stmt2, expectedSQL+expected.sql+";\n", expected.args...)
|
||||
|
||||
dest2 := []model.AllTypes{}
|
||||
err = stmt2.Query(db, &dest2)
|
||||
|
|
@ -540,68 +541,68 @@ FROM`
|
|||
}
|
||||
|
||||
var allTypesRow0 = model.AllTypes{
|
||||
SmallintPtr: int16Ptr(1),
|
||||
SmallintPtr: Int16Ptr(1),
|
||||
Smallint: 1,
|
||||
IntegerPtr: int32Ptr(300),
|
||||
IntegerPtr: Int32Ptr(300),
|
||||
Integer: 300,
|
||||
BigintPtr: int64Ptr(50000),
|
||||
BigintPtr: Int64Ptr(50000),
|
||||
Bigint: 5000,
|
||||
DecimalPtr: float64Ptr(11.44),
|
||||
DecimalPtr: Float64Ptr(11.44),
|
||||
Decimal: 11.44,
|
||||
NumericPtr: float64Ptr(55.77),
|
||||
NumericPtr: Float64Ptr(55.77),
|
||||
Numeric: 55.77,
|
||||
RealPtr: float32Ptr(99.1),
|
||||
RealPtr: Float32Ptr(99.1),
|
||||
Real: 99.1,
|
||||
DoublePrecisionPtr: float64Ptr(11111111.22),
|
||||
DoublePrecisionPtr: Float64Ptr(11111111.22),
|
||||
DoublePrecision: 11111111.22,
|
||||
Smallserial: 1,
|
||||
Serial: 1,
|
||||
Bigserial: 1,
|
||||
//MoneyPtr: nil,
|
||||
//Money:
|
||||
CharacterVaryingPtr: stringPtr("ABBA"),
|
||||
CharacterVaryingPtr: StringPtr("ABBA"),
|
||||
CharacterVarying: "ABBA",
|
||||
CharacterPtr: stringPtr("JOHN "),
|
||||
CharacterPtr: StringPtr("JOHN "),
|
||||
Character: "JOHN ",
|
||||
TextPtr: stringPtr("Some text"),
|
||||
TextPtr: StringPtr("Some text"),
|
||||
Text: "Some text",
|
||||
ByteaPtr: byteArrayPtr([]byte("bytea")),
|
||||
ByteaPtr: ByteArrayPtr([]byte("bytea")),
|
||||
Bytea: []byte("bytea"),
|
||||
TimestampzPtr: timestampWithTimeZone("1999-01-08 13:05:06 +0100 CET", 0),
|
||||
Timestampz: *timestampWithTimeZone("1999-01-08 13:05:06 +0100 CET", 0),
|
||||
TimestampPtr: timestampWithoutTimeZone("1999-01-08 04:05:06", 0),
|
||||
Timestamp: *timestampWithoutTimeZone("1999-01-08 04:05:06", 0),
|
||||
DatePtr: timestampWithoutTimeZone("1999-01-08 00:00:00", 0),
|
||||
Date: *timestampWithoutTimeZone("1999-01-08 00:00:00", 0),
|
||||
TimezPtr: timeWithTimeZone("04:05:06 -0800"),
|
||||
Timez: *timeWithTimeZone("04:05:06 -0800"),
|
||||
TimePtr: timeWithoutTimeZone("04:05:06"),
|
||||
Time: *timeWithoutTimeZone("04:05:06"),
|
||||
IntervalPtr: stringPtr("3 days 04:05:06"),
|
||||
TimestampzPtr: TimestampWithTimeZone("1999-01-08 13:05:06 +0100 CET", 0),
|
||||
Timestampz: *TimestampWithTimeZone("1999-01-08 13:05:06 +0100 CET", 0),
|
||||
TimestampPtr: testutils.TimestampWithoutTimeZone("1999-01-08 04:05:06", 0),
|
||||
Timestamp: *testutils.TimestampWithoutTimeZone("1999-01-08 04:05:06", 0),
|
||||
DatePtr: testutils.TimestampWithoutTimeZone("1999-01-08 00:00:00", 0),
|
||||
Date: *testutils.TimestampWithoutTimeZone("1999-01-08 00:00:00", 0),
|
||||
TimezPtr: TimeWithTimeZone("04:05:06 -0800"),
|
||||
Timez: *TimeWithTimeZone("04:05:06 -0800"),
|
||||
TimePtr: TimeWithoutTimeZone("04:05:06"),
|
||||
Time: *TimeWithoutTimeZone("04:05:06"),
|
||||
IntervalPtr: StringPtr("3 days 04:05:06"),
|
||||
Interval: "3 days 04:05:06",
|
||||
BooleanPtr: boolPtr(true),
|
||||
BooleanPtr: BoolPtr(true),
|
||||
Boolean: false,
|
||||
PointPtr: stringPtr("(2,3)"),
|
||||
BitPtr: stringPtr("101"),
|
||||
PointPtr: StringPtr("(2,3)"),
|
||||
BitPtr: StringPtr("101"),
|
||||
Bit: "101",
|
||||
BitVaryingPtr: stringPtr("101111"),
|
||||
BitVaryingPtr: StringPtr("101111"),
|
||||
BitVarying: "101111",
|
||||
TsvectorPtr: stringPtr("'supernova':1"),
|
||||
TsvectorPtr: StringPtr("'supernova':1"),
|
||||
Tsvector: "'supernova':1",
|
||||
UUIDPtr: uuidPtr("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"),
|
||||
UUIDPtr: UUIDPtr("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"),
|
||||
UUID: uuid.MustParse("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"),
|
||||
XMLPtr: stringPtr("<Sub>abc</Sub>"),
|
||||
XMLPtr: StringPtr("<Sub>abc</Sub>"),
|
||||
XML: "<Sub>abc</Sub>",
|
||||
JSONPtr: stringPtr(`{"a": 1, "b": 3}`),
|
||||
JSONPtr: StringPtr(`{"a": 1, "b": 3}`),
|
||||
JSON: `{"a": 1, "b": 3}`,
|
||||
JsonbPtr: stringPtr(`{"a": 1, "b": 3}`),
|
||||
JsonbPtr: StringPtr(`{"a": 1, "b": 3}`),
|
||||
Jsonb: `{"a": 1, "b": 3}`,
|
||||
IntegerArrayPtr: stringPtr("{1,2,3}"),
|
||||
IntegerArrayPtr: StringPtr("{1,2,3}"),
|
||||
IntegerArray: "{1,2,3}",
|
||||
TextArrayPtr: stringPtr("{breakfast,consulting}"),
|
||||
TextArrayPtr: StringPtr("{breakfast,consulting}"),
|
||||
TextArray: "{breakfast,consulting}",
|
||||
JsonbArray: `{"{\"a\": 1, \"b\": 2}","{\"a\": 3, \"b\": 4}"}`,
|
||||
TextMultiDimArrayPtr: stringPtr("{{meeting,lunch},{training,presentation}}"),
|
||||
TextMultiDimArrayPtr: StringPtr("{{meeting,lunch},{training,presentation}}"),
|
||||
TextMultiDimArray: "{{meeting,lunch},{training,presentation}}",
|
||||
}
|
||||
|
||||
|
|
@ -634,15 +635,15 @@ var allTypesRow1 = model.AllTypes{
|
|||
ByteaPtr: nil,
|
||||
Bytea: []byte("bytea"),
|
||||
TimestampzPtr: nil,
|
||||
Timestampz: *timestampWithTimeZone("1999-01-08 13:05:06 +0100 CET", 0),
|
||||
Timestampz: *TimestampWithTimeZone("1999-01-08 13:05:06 +0100 CET", 0),
|
||||
TimestampPtr: nil,
|
||||
Timestamp: *timestampWithoutTimeZone("1999-01-08 04:05:06", 0),
|
||||
Timestamp: *testutils.TimestampWithoutTimeZone("1999-01-08 04:05:06", 0),
|
||||
DatePtr: nil,
|
||||
Date: *timestampWithoutTimeZone("1999-01-08 00:00:00", 0),
|
||||
Date: *testutils.TimestampWithoutTimeZone("1999-01-08 00:00:00", 0),
|
||||
TimezPtr: nil,
|
||||
Timez: *timeWithTimeZone("04:05:06 -0800"),
|
||||
Timez: *TimeWithTimeZone("04:05:06 -0800"),
|
||||
TimePtr: nil,
|
||||
Time: *timeWithoutTimeZone("04:05:06"),
|
||||
Time: *TimeWithoutTimeZone("04:05:06"),
|
||||
IntervalPtr: nil,
|
||||
Interval: "3 days 04:05:06",
|
||||
BooleanPtr: nil,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/chinook/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/chinook/table"
|
||||
"gotest.tools/assert"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -20,7 +16,7 @@ func TestSelect(t *testing.T) {
|
|||
SELECT(Album.AllColumns).
|
||||
ORDER_BY(Album.AlbumId.ASC())
|
||||
|
||||
assertStatementSql(t, stmt, `
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT "Album"."AlbumId" AS "Album.AlbumId",
|
||||
"Album"."Title" AS "Album.Title",
|
||||
"Album"."ArtistId" AS "Album.ArtistId"
|
||||
|
|
@ -106,7 +102,7 @@ func TestJoinEverything(t *testing.T) {
|
|||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 275)
|
||||
assertJSONFile(t, "./testdata/joined_everything.json", dest)
|
||||
testutils.AssertJSONFile(t, "./testdata/joined_everything.json", dest)
|
||||
}
|
||||
|
||||
func TestSelfJoin(t *testing.T) {
|
||||
|
|
@ -130,7 +126,7 @@ func TestSelfJoin(t *testing.T) {
|
|||
).
|
||||
ORDER_BY(Employee.EmployeeId)
|
||||
|
||||
assertStatementSql(t, stmt, `
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT "Employee"."EmployeeId" AS "Employee.EmployeeId",
|
||||
"Employee"."FirstName" AS "Employee.FirstName",
|
||||
"Employee"."LastName" AS "Employee.LastName",
|
||||
|
|
@ -146,7 +142,7 @@ ORDER BY "Employee"."EmployeeId";
|
|||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 8)
|
||||
assertJSON(t, dest[0:2], `
|
||||
testutils.AssertJSON(t, dest[0:2], `
|
||||
[
|
||||
{
|
||||
"EmployeeId": 1,
|
||||
|
|
@ -214,7 +210,7 @@ func TestUnionForQuotedNames(t *testing.T) {
|
|||
ORDER_BY(Album.AlbumId)
|
||||
|
||||
//fmt.Println(stmt.DebugSql())
|
||||
assertStatementSql(t, stmt, `
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
(
|
||||
(
|
||||
SELECT "Album"."AlbumId" AS "Album.AlbumId",
|
||||
|
|
@ -298,7 +294,7 @@ func TestSubQueriesForQuotedNames(t *testing.T) {
|
|||
SELECT(first10Artist.AllColumns(), first10Albums.AllColumns()).
|
||||
ORDER_BY(artistID)
|
||||
|
||||
assertStatementSql(t, stmt, `
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT "first10Artist"."Artist.ArtistId" AS "Artist.ArtistId",
|
||||
"first10Artist"."Artist.Name" AS "Artist.Name",
|
||||
"first10Albums"."Album.AlbumId" AS "Album.AlbumId",
|
||||
|
|
@ -335,43 +331,6 @@ ORDER BY "first10Artist"."Artist.ArtistId";
|
|||
//spew.Dump(dest)
|
||||
}
|
||||
|
||||
func assertJSON(t *testing.T, data interface{}, expectedJSON string) {
|
||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, "\n"+string(jsonData)+"\n", expectedJSON)
|
||||
}
|
||||
|
||||
func assertJSONFile(t *testing.T, jsonFilePath string, data interface{}) {
|
||||
fileJSONData, err := ioutil.ReadFile(jsonFilePath)
|
||||
assert.NilError(t, err)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
fileJSONData = bytes.Replace(fileJSONData, []byte("\r\n"), []byte("\n"), -1)
|
||||
}
|
||||
|
||||
jsonData, err := json.MarshalIndent(data, "", "\t")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Assert(t, string(fileJSONData) == string(jsonData))
|
||||
//assert.Equal(t, string(fileJSONData), string(jsonData))
|
||||
}
|
||||
|
||||
func jsonPrint(v interface{}) {
|
||||
jsonText, _ := json.MarshalIndent(v, "", "\t")
|
||||
fmt.Println(string(jsonText))
|
||||
}
|
||||
|
||||
func jsonSave(path string, v interface{}) {
|
||||
jsonText, _ := json.MarshalIndent(v, "", "\t")
|
||||
|
||||
err := ioutil.WriteFile(path, jsonText, 0644)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var album1 = model.Album{
|
||||
AlbumId: 1,
|
||||
Title: "For Those About To Rock We Salute You",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package dbconfig
|
|||
|
||||
import "fmt"
|
||||
|
||||
// test database connection parameters
|
||||
// Postgres test database connection parameters
|
||||
const (
|
||||
Host = "localhost"
|
||||
Port = 5432
|
||||
|
|
@ -11,5 +11,15 @@ const (
|
|||
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)
|
||||
// PostgresConnectString is PostgreSQL test database connection string
|
||||
var PostgresConnectString = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", Host, Port, User, Password, DBName)
|
||||
|
||||
// MySQL test database connection parameters
|
||||
const (
|
||||
MySqLHost = "localhost"
|
||||
MySQLPort = 3306
|
||||
MySQLUser = "jet"
|
||||
MySQLPassword = "jet"
|
||||
)
|
||||
|
||||
var MySQLConnectionString = fmt.Sprintf("%s:%s@tcp(%s:%d)/", MySQLUser, MySQLPassword, MySqLHost, MySQLPort)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package tests
|
|||
import (
|
||||
"context"
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"gotest.tools/assert"
|
||||
|
|
@ -21,7 +22,7 @@ WHERE link.name IN ('Gmail', 'Outlook');
|
|||
DELETE().
|
||||
WHERE(Link.Name.IN(String("Gmail"), String("Outlook")))
|
||||
|
||||
assertStatementSql(t, deleteStmt, expectedSQL, "Gmail", "Outlook")
|
||||
testutils.AssertStatementSql(t, deleteStmt, expectedSQL, "Gmail", "Outlook")
|
||||
assertExec(t, deleteStmt, 2)
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ RETURNING link.id AS "link.id",
|
|||
WHERE(Link.Name.IN(String("Gmail"), String("Outlook"))).
|
||||
RETURNING(Link.AllColumns)
|
||||
|
||||
assertStatementSql(t, deleteStmt, expectedSQL, "Gmail", "Outlook")
|
||||
testutils.AssertStatementSql(t, deleteStmt, expectedSQL, "Gmail", "Outlook")
|
||||
|
||||
dest := []model.Link{}
|
||||
|
||||
|
|
|
|||
46431
tests/init/data/mysql/sakila-data.sql
Normal file
46431
tests/init/data/mysql/sakila-data.sql
Normal file
File diff suppressed because one or more lines are too long
648
tests/init/data/mysql/sakila-schema.sql
Normal file
648
tests/init/data/mysql/sakila-schema.sql
Normal file
|
|
@ -0,0 +1,648 @@
|
|||
-- Sakila Sample Database Schema
|
||||
-- Version 1.0
|
||||
|
||||
-- Copyright (c) 2006, 2015, Oracle and/or its affiliates.
|
||||
-- All rights reserved.
|
||||
|
||||
-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
-- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
-- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
-- * Neither the name of Oracle nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
|
||||
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
|
||||
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';
|
||||
|
||||
DROP SCHEMA IF EXISTS sakila;
|
||||
CREATE SCHEMA sakila;
|
||||
USE sakila;
|
||||
|
||||
--
|
||||
-- Table structure for table `actor`
|
||||
--
|
||||
|
||||
CREATE TABLE actor (
|
||||
actor_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
first_name VARCHAR(45) NOT NULL,
|
||||
last_name VARCHAR(45) NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (actor_id),
|
||||
KEY idx_actor_last_name (last_name)
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `address`
|
||||
--
|
||||
|
||||
CREATE TABLE address (
|
||||
address_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
address VARCHAR(50) NOT NULL,
|
||||
address2 VARCHAR(50) DEFAULT NULL,
|
||||
district VARCHAR(20) NOT NULL,
|
||||
city_id SMALLINT UNSIGNED NOT NULL,
|
||||
postal_code VARCHAR(10) DEFAULT NULL,
|
||||
phone VARCHAR(20) NOT NULL,
|
||||
/*!50705 location GEOMETRY NOT NULL,*/
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (address_id),
|
||||
KEY idx_fk_city_id (city_id),
|
||||
/*!50705 SPATIAL KEY `idx_location` (location),*/
|
||||
CONSTRAINT `fk_address_city` FOREIGN KEY (city_id) REFERENCES city (city_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `category`
|
||||
--
|
||||
|
||||
CREATE TABLE category (
|
||||
category_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
name VARCHAR(25) NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (category_id)
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `city`
|
||||
--
|
||||
|
||||
CREATE TABLE city (
|
||||
city_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
city VARCHAR(50) NOT NULL,
|
||||
country_id SMALLINT UNSIGNED NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (city_id),
|
||||
KEY idx_fk_country_id (country_id),
|
||||
CONSTRAINT `fk_city_country` FOREIGN KEY (country_id) REFERENCES country (country_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `country`
|
||||
--
|
||||
|
||||
CREATE TABLE country (
|
||||
country_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
country VARCHAR(50) NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (country_id)
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `customer`
|
||||
--
|
||||
|
||||
CREATE TABLE customer (
|
||||
customer_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
store_id TINYINT UNSIGNED NOT NULL,
|
||||
first_name VARCHAR(45) NOT NULL,
|
||||
last_name VARCHAR(45) NOT NULL,
|
||||
email VARCHAR(50) DEFAULT NULL,
|
||||
address_id SMALLINT UNSIGNED NOT NULL,
|
||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
create_date DATETIME NOT NULL,
|
||||
last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (customer_id),
|
||||
KEY idx_fk_store_id (store_id),
|
||||
KEY idx_fk_address_id (address_id),
|
||||
KEY idx_last_name (last_name),
|
||||
CONSTRAINT fk_customer_address FOREIGN KEY (address_id) REFERENCES address (address_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_customer_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `film`
|
||||
--
|
||||
|
||||
CREATE TABLE film (
|
||||
film_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT DEFAULT NULL,
|
||||
release_year YEAR DEFAULT NULL,
|
||||
language_id TINYINT UNSIGNED NOT NULL,
|
||||
original_language_id TINYINT UNSIGNED DEFAULT NULL,
|
||||
rental_duration TINYINT UNSIGNED NOT NULL DEFAULT 3,
|
||||
rental_rate DECIMAL(4,2) NOT NULL DEFAULT 4.99,
|
||||
length SMALLINT UNSIGNED DEFAULT NULL,
|
||||
replacement_cost DECIMAL(5,2) NOT NULL DEFAULT 19.99,
|
||||
rating ENUM('G','PG','PG-13','R','NC-17') DEFAULT 'G',
|
||||
special_features SET('Trailers','Commentaries','Deleted Scenes','Behind the Scenes') DEFAULT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (film_id),
|
||||
KEY idx_title (title),
|
||||
KEY idx_fk_language_id (language_id),
|
||||
KEY idx_fk_original_language_id (original_language_id),
|
||||
CONSTRAINT fk_film_language FOREIGN KEY (language_id) REFERENCES language (language_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_film_language_original FOREIGN KEY (original_language_id) REFERENCES language (language_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `film_actor`
|
||||
--
|
||||
|
||||
CREATE TABLE film_actor (
|
||||
actor_id SMALLINT UNSIGNED NOT NULL,
|
||||
film_id SMALLINT UNSIGNED NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (actor_id,film_id),
|
||||
KEY idx_fk_film_id (`film_id`),
|
||||
CONSTRAINT fk_film_actor_actor FOREIGN KEY (actor_id) REFERENCES actor (actor_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_film_actor_film FOREIGN KEY (film_id) REFERENCES film (film_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `film_category`
|
||||
--
|
||||
|
||||
CREATE TABLE film_category (
|
||||
film_id SMALLINT UNSIGNED NOT NULL,
|
||||
category_id TINYINT UNSIGNED NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (film_id, category_id),
|
||||
CONSTRAINT fk_film_category_film FOREIGN KEY (film_id) REFERENCES film (film_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_film_category_category FOREIGN KEY (category_id) REFERENCES category (category_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `film_text`
|
||||
--
|
||||
-- InnoDB added FULLTEXT support in 5.6.10. If you use an
|
||||
-- earlier version, then consider upgrading (recommended) or
|
||||
-- changing InnoDB to MyISAM as the film_text engine
|
||||
--
|
||||
|
||||
CREATE TABLE film_text (
|
||||
film_id SMALLINT NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
PRIMARY KEY (film_id),
|
||||
FULLTEXT KEY idx_title_description (title,description)
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Triggers for loading film_text from film
|
||||
--
|
||||
|
||||
DELIMITER ;;
|
||||
CREATE TRIGGER `ins_film` AFTER INSERT ON `film` FOR EACH ROW BEGIN
|
||||
INSERT INTO film_text (film_id, title, description)
|
||||
VALUES (new.film_id, new.title, new.description);
|
||||
END;;
|
||||
|
||||
|
||||
CREATE TRIGGER `upd_film` AFTER UPDATE ON `film` FOR EACH ROW BEGIN
|
||||
IF (old.title != new.title) OR (old.description != new.description) OR (old.film_id != new.film_id)
|
||||
THEN
|
||||
UPDATE film_text
|
||||
SET title=new.title,
|
||||
description=new.description,
|
||||
film_id=new.film_id
|
||||
WHERE film_id=old.film_id;
|
||||
END IF;
|
||||
END;;
|
||||
|
||||
|
||||
CREATE TRIGGER `del_film` AFTER DELETE ON `film` FOR EACH ROW BEGIN
|
||||
DELETE FROM film_text WHERE film_id = old.film_id;
|
||||
END;;
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
--
|
||||
-- Table structure for table `inventory`
|
||||
--
|
||||
|
||||
CREATE TABLE inventory (
|
||||
inventory_id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
film_id SMALLINT UNSIGNED NOT NULL,
|
||||
store_id TINYINT UNSIGNED NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (inventory_id),
|
||||
KEY idx_fk_film_id (film_id),
|
||||
KEY idx_store_id_film_id (store_id,film_id),
|
||||
CONSTRAINT fk_inventory_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_inventory_film FOREIGN KEY (film_id) REFERENCES film (film_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `language`
|
||||
--
|
||||
|
||||
CREATE TABLE language (
|
||||
language_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
name CHAR(20) NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (language_id)
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `payment`
|
||||
--
|
||||
|
||||
CREATE TABLE payment (
|
||||
payment_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
customer_id SMALLINT UNSIGNED NOT NULL,
|
||||
staff_id TINYINT UNSIGNED NOT NULL,
|
||||
rental_id INT DEFAULT NULL,
|
||||
amount DECIMAL(5,2) NOT NULL,
|
||||
payment_date DATETIME NOT NULL,
|
||||
last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (payment_id),
|
||||
KEY idx_fk_staff_id (staff_id),
|
||||
KEY idx_fk_customer_id (customer_id),
|
||||
CONSTRAINT fk_payment_rental FOREIGN KEY (rental_id) REFERENCES rental (rental_id) ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_payment_customer FOREIGN KEY (customer_id) REFERENCES customer (customer_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_payment_staff FOREIGN KEY (staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
--
|
||||
-- Table structure for table `rental`
|
||||
--
|
||||
|
||||
CREATE TABLE rental (
|
||||
rental_id INT NOT NULL AUTO_INCREMENT,
|
||||
rental_date DATETIME NOT NULL,
|
||||
inventory_id MEDIUMINT UNSIGNED NOT NULL,
|
||||
customer_id SMALLINT UNSIGNED NOT NULL,
|
||||
return_date DATETIME DEFAULT NULL,
|
||||
staff_id TINYINT UNSIGNED NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (rental_id),
|
||||
UNIQUE KEY (rental_date,inventory_id,customer_id),
|
||||
KEY idx_fk_inventory_id (inventory_id),
|
||||
KEY idx_fk_customer_id (customer_id),
|
||||
KEY idx_fk_staff_id (staff_id),
|
||||
CONSTRAINT fk_rental_staff FOREIGN KEY (staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_rental_inventory FOREIGN KEY (inventory_id) REFERENCES inventory (inventory_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_rental_customer FOREIGN KEY (customer_id) REFERENCES customer (customer_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `staff`
|
||||
--
|
||||
|
||||
CREATE TABLE staff (
|
||||
staff_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
first_name VARCHAR(45) NOT NULL,
|
||||
last_name VARCHAR(45) NOT NULL,
|
||||
address_id SMALLINT UNSIGNED NOT NULL,
|
||||
picture BLOB DEFAULT NULL,
|
||||
email VARCHAR(50) DEFAULT NULL,
|
||||
store_id TINYINT UNSIGNED NOT NULL,
|
||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
username VARCHAR(16) NOT NULL,
|
||||
password VARCHAR(40) BINARY DEFAULT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (staff_id),
|
||||
KEY idx_fk_store_id (store_id),
|
||||
KEY idx_fk_address_id (address_id),
|
||||
CONSTRAINT fk_staff_store FOREIGN KEY (store_id) REFERENCES store (store_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_staff_address FOREIGN KEY (address_id) REFERENCES address (address_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Table structure for table `store`
|
||||
--
|
||||
|
||||
CREATE TABLE store (
|
||||
store_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
manager_staff_id TINYINT UNSIGNED NOT NULL,
|
||||
address_id SMALLINT UNSIGNED NOT NULL,
|
||||
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (store_id),
|
||||
UNIQUE KEY idx_unique_manager (manager_staff_id),
|
||||
KEY idx_fk_address_id (address_id),
|
||||
CONSTRAINT fk_store_staff FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
CONSTRAINT fk_store_address FOREIGN KEY (address_id) REFERENCES address (address_id) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- View structure for view `customer_list`
|
||||
--
|
||||
|
||||
CREATE VIEW customer_list
|
||||
AS
|
||||
SELECT cu.customer_id AS ID, CONCAT(cu.first_name, _utf8' ', cu.last_name) AS name, a.address AS address, a.postal_code AS `zip code`,
|
||||
a.phone AS phone, city.city AS city, country.country AS country, IF(cu.active, _utf8'active',_utf8'') AS notes, cu.store_id AS SID
|
||||
FROM customer AS cu JOIN address AS a ON cu.address_id = a.address_id JOIN city ON a.city_id = city.city_id
|
||||
JOIN country ON city.country_id = country.country_id;
|
||||
|
||||
--
|
||||
-- View structure for view `film_list`
|
||||
--
|
||||
|
||||
CREATE VIEW film_list
|
||||
AS
|
||||
SELECT film.film_id AS FID, film.title AS title, film.description AS description, category.name AS category, film.rental_rate AS price,
|
||||
film.length AS length, film.rating AS rating, GROUP_CONCAT(CONCAT(actor.first_name, _utf8' ', actor.last_name) SEPARATOR ', ') AS actors
|
||||
FROM category LEFT JOIN film_category ON category.category_id = film_category.category_id LEFT JOIN film ON film_category.film_id = film.film_id
|
||||
JOIN film_actor ON film.film_id = film_actor.film_id
|
||||
JOIN actor ON film_actor.actor_id = actor.actor_id
|
||||
GROUP BY film.film_id, category.name;
|
||||
|
||||
--
|
||||
-- View structure for view `nicer_but_slower_film_list`
|
||||
--
|
||||
|
||||
CREATE VIEW nicer_but_slower_film_list
|
||||
AS
|
||||
SELECT film.film_id AS FID, film.title AS title, film.description AS description, category.name AS category, film.rental_rate AS price,
|
||||
film.length AS length, film.rating AS rating, GROUP_CONCAT(CONCAT(CONCAT(UCASE(SUBSTR(actor.first_name,1,1)),
|
||||
LCASE(SUBSTR(actor.first_name,2,LENGTH(actor.first_name))),_utf8' ',CONCAT(UCASE(SUBSTR(actor.last_name,1,1)),
|
||||
LCASE(SUBSTR(actor.last_name,2,LENGTH(actor.last_name)))))) SEPARATOR ', ') AS actors
|
||||
FROM category LEFT JOIN film_category ON category.category_id = film_category.category_id LEFT JOIN film ON film_category.film_id = film.film_id
|
||||
JOIN film_actor ON film.film_id = film_actor.film_id
|
||||
JOIN actor ON film_actor.actor_id = actor.actor_id
|
||||
GROUP BY film.film_id, category.name;
|
||||
|
||||
--
|
||||
-- View structure for view `staff_list`
|
||||
--
|
||||
|
||||
CREATE VIEW staff_list
|
||||
AS
|
||||
SELECT s.staff_id AS ID, CONCAT(s.first_name, _utf8' ', s.last_name) AS name, a.address AS address, a.postal_code AS `zip code`, a.phone AS phone,
|
||||
city.city AS city, country.country AS country, s.store_id AS SID
|
||||
FROM staff AS s JOIN address AS a ON s.address_id = a.address_id JOIN city ON a.city_id = city.city_id
|
||||
JOIN country ON city.country_id = country.country_id;
|
||||
|
||||
--
|
||||
-- View structure for view `sales_by_store`
|
||||
--
|
||||
|
||||
CREATE VIEW sales_by_store
|
||||
AS
|
||||
SELECT
|
||||
CONCAT(c.city, _utf8',', cy.country) AS store
|
||||
, CONCAT(m.first_name, _utf8' ', m.last_name) AS manager
|
||||
, SUM(p.amount) AS total_sales
|
||||
FROM payment AS p
|
||||
INNER JOIN rental AS r ON p.rental_id = r.rental_id
|
||||
INNER JOIN inventory AS i ON r.inventory_id = i.inventory_id
|
||||
INNER JOIN store AS s ON i.store_id = s.store_id
|
||||
INNER JOIN address AS a ON s.address_id = a.address_id
|
||||
INNER JOIN city AS c ON a.city_id = c.city_id
|
||||
INNER JOIN country AS cy ON c.country_id = cy.country_id
|
||||
INNER JOIN staff AS m ON s.manager_staff_id = m.staff_id
|
||||
GROUP BY s.store_id
|
||||
ORDER BY cy.country, c.city;
|
||||
|
||||
--
|
||||
-- View structure for view `sales_by_film_category`
|
||||
--
|
||||
-- Note that total sales will add up to >100% because
|
||||
-- some titles belong to more than 1 category
|
||||
--
|
||||
|
||||
CREATE VIEW sales_by_film_category
|
||||
AS
|
||||
SELECT
|
||||
c.name AS category
|
||||
, SUM(p.amount) AS total_sales
|
||||
FROM payment AS p
|
||||
INNER JOIN rental AS r ON p.rental_id = r.rental_id
|
||||
INNER JOIN inventory AS i ON r.inventory_id = i.inventory_id
|
||||
INNER JOIN film AS f ON i.film_id = f.film_id
|
||||
INNER JOIN film_category AS fc ON f.film_id = fc.film_id
|
||||
INNER JOIN category AS c ON fc.category_id = c.category_id
|
||||
GROUP BY c.name
|
||||
ORDER BY total_sales DESC;
|
||||
|
||||
--
|
||||
-- View structure for view `actor_info`
|
||||
--
|
||||
|
||||
CREATE DEFINER=CURRENT_USER SQL SECURITY INVOKER VIEW actor_info
|
||||
AS
|
||||
SELECT
|
||||
a.actor_id,
|
||||
a.first_name,
|
||||
a.last_name,
|
||||
GROUP_CONCAT(DISTINCT CONCAT(c.name, ': ',
|
||||
(SELECT GROUP_CONCAT(f.title ORDER BY f.title SEPARATOR ', ')
|
||||
FROM sakila.film f
|
||||
INNER JOIN sakila.film_category fc
|
||||
ON f.film_id = fc.film_id
|
||||
INNER JOIN sakila.film_actor fa
|
||||
ON f.film_id = fa.film_id
|
||||
WHERE fc.category_id = c.category_id
|
||||
AND fa.actor_id = a.actor_id
|
||||
)
|
||||
)
|
||||
ORDER BY c.name SEPARATOR '; ')
|
||||
AS film_info
|
||||
FROM sakila.actor a
|
||||
LEFT JOIN sakila.film_actor fa
|
||||
ON a.actor_id = fa.actor_id
|
||||
LEFT JOIN sakila.film_category fc
|
||||
ON fa.film_id = fc.film_id
|
||||
LEFT JOIN sakila.category c
|
||||
ON fc.category_id = c.category_id
|
||||
GROUP BY a.actor_id, a.first_name, a.last_name;
|
||||
|
||||
--
|
||||
-- Procedure structure for procedure `rewards_report`
|
||||
--
|
||||
|
||||
DELIMITER //
|
||||
|
||||
CREATE PROCEDURE rewards_report (
|
||||
IN min_monthly_purchases TINYINT UNSIGNED
|
||||
, IN min_dollar_amount_purchased DECIMAL(10,2) UNSIGNED
|
||||
, OUT count_rewardees INT
|
||||
)
|
||||
LANGUAGE SQL
|
||||
NOT DETERMINISTIC
|
||||
READS SQL DATA
|
||||
SQL SECURITY DEFINER
|
||||
COMMENT 'Provides a customizable report on best customers'
|
||||
proc: BEGIN
|
||||
|
||||
DECLARE last_month_start DATE;
|
||||
DECLARE last_month_end DATE;
|
||||
|
||||
/* Some sanity checks... */
|
||||
IF min_monthly_purchases = 0 THEN
|
||||
SELECT 'Minimum monthly purchases parameter must be > 0';
|
||||
LEAVE proc;
|
||||
END IF;
|
||||
IF min_dollar_amount_purchased = 0.00 THEN
|
||||
SELECT 'Minimum monthly dollar amount purchased parameter must be > $0.00';
|
||||
LEAVE proc;
|
||||
END IF;
|
||||
|
||||
/* Determine start and end time periods */
|
||||
SET last_month_start = DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH);
|
||||
SET last_month_start = STR_TO_DATE(CONCAT(YEAR(last_month_start),'-',MONTH(last_month_start),'-01'),'%Y-%m-%d');
|
||||
SET last_month_end = LAST_DAY(last_month_start);
|
||||
|
||||
/*
|
||||
Create a temporary storage area for
|
||||
Customer IDs.
|
||||
*/
|
||||
CREATE TEMPORARY TABLE tmpCustomer (customer_id SMALLINT UNSIGNED NOT NULL PRIMARY KEY);
|
||||
|
||||
/*
|
||||
Find all customers meeting the
|
||||
monthly purchase requirements
|
||||
*/
|
||||
INSERT INTO tmpCustomer (customer_id)
|
||||
SELECT p.customer_id
|
||||
FROM payment AS p
|
||||
WHERE DATE(p.payment_date) BETWEEN last_month_start AND last_month_end
|
||||
GROUP BY customer_id
|
||||
HAVING SUM(p.amount) > min_dollar_amount_purchased
|
||||
AND COUNT(customer_id) > min_monthly_purchases;
|
||||
|
||||
/* Populate OUT parameter with count of found customers */
|
||||
SELECT COUNT(*) FROM tmpCustomer INTO count_rewardees;
|
||||
|
||||
/*
|
||||
Output ALL customer information of matching rewardees.
|
||||
Customize output as needed.
|
||||
*/
|
||||
SELECT c.*
|
||||
FROM tmpCustomer AS t
|
||||
INNER JOIN customer AS c ON t.customer_id = c.customer_id;
|
||||
|
||||
/* Clean up */
|
||||
DROP TABLE tmpCustomer;
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
DELIMITER $$
|
||||
|
||||
CREATE FUNCTION get_customer_balance(p_customer_id INT, p_effective_date DATETIME) RETURNS DECIMAL(5,2)
|
||||
DETERMINISTIC
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
|
||||
#OK, WE NEED TO CALCULATE THE CURRENT BALANCE GIVEN A CUSTOMER_ID AND A DATE
|
||||
#THAT WE WANT THE BALANCE TO BE EFFECTIVE FOR. THE BALANCE IS:
|
||||
# 1) RENTAL FEES FOR ALL PREVIOUS RENTALS
|
||||
# 2) ONE DOLLAR FOR EVERY DAY THE PREVIOUS RENTALS ARE OVERDUE
|
||||
# 3) IF A FILM IS MORE THAN RENTAL_DURATION * 2 OVERDUE, CHARGE THE REPLACEMENT_COST
|
||||
# 4) SUBTRACT ALL PAYMENTS MADE BEFORE THE DATE SPECIFIED
|
||||
|
||||
DECLARE v_rentfees DECIMAL(5,2); #FEES PAID TO RENT THE VIDEOS INITIALLY
|
||||
DECLARE v_overfees INTEGER; #LATE FEES FOR PRIOR RENTALS
|
||||
DECLARE v_payments DECIMAL(5,2); #SUM OF PAYMENTS MADE PREVIOUSLY
|
||||
|
||||
SELECT IFNULL(SUM(film.rental_rate),0) INTO v_rentfees
|
||||
FROM film, inventory, rental
|
||||
WHERE film.film_id = inventory.film_id
|
||||
AND inventory.inventory_id = rental.inventory_id
|
||||
AND rental.rental_date <= p_effective_date
|
||||
AND rental.customer_id = p_customer_id;
|
||||
|
||||
SELECT IFNULL(SUM(IF((TO_DAYS(rental.return_date) - TO_DAYS(rental.rental_date)) > film.rental_duration,
|
||||
((TO_DAYS(rental.return_date) - TO_DAYS(rental.rental_date)) - film.rental_duration),0)),0) INTO v_overfees
|
||||
FROM rental, inventory, film
|
||||
WHERE film.film_id = inventory.film_id
|
||||
AND inventory.inventory_id = rental.inventory_id
|
||||
AND rental.rental_date <= p_effective_date
|
||||
AND rental.customer_id = p_customer_id;
|
||||
|
||||
|
||||
SELECT IFNULL(SUM(payment.amount),0) INTO v_payments
|
||||
FROM payment
|
||||
|
||||
WHERE payment.payment_date <= p_effective_date
|
||||
AND payment.customer_id = p_customer_id;
|
||||
|
||||
RETURN v_rentfees + v_overfees - v_payments;
|
||||
END $$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
DELIMITER $$
|
||||
|
||||
CREATE PROCEDURE film_in_stock(IN p_film_id INT, IN p_store_id INT, OUT p_film_count INT)
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
SELECT inventory_id
|
||||
FROM inventory
|
||||
WHERE film_id = p_film_id
|
||||
AND store_id = p_store_id
|
||||
AND inventory_in_stock(inventory_id);
|
||||
|
||||
SELECT FOUND_ROWS() INTO p_film_count;
|
||||
END $$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
DELIMITER $$
|
||||
|
||||
CREATE PROCEDURE film_not_in_stock(IN p_film_id INT, IN p_store_id INT, OUT p_film_count INT)
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
SELECT inventory_id
|
||||
FROM inventory
|
||||
WHERE film_id = p_film_id
|
||||
AND store_id = p_store_id
|
||||
AND NOT inventory_in_stock(inventory_id);
|
||||
|
||||
SELECT FOUND_ROWS() INTO p_film_count;
|
||||
END $$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
DELIMITER $$
|
||||
|
||||
CREATE FUNCTION inventory_held_by_customer(p_inventory_id INT) RETURNS INT
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
DECLARE v_customer_id INT;
|
||||
DECLARE EXIT HANDLER FOR NOT FOUND RETURN NULL;
|
||||
|
||||
SELECT customer_id INTO v_customer_id
|
||||
FROM rental
|
||||
WHERE return_date IS NULL
|
||||
AND inventory_id = p_inventory_id;
|
||||
|
||||
RETURN v_customer_id;
|
||||
END $$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
DELIMITER $$
|
||||
|
||||
CREATE FUNCTION inventory_in_stock(p_inventory_id INT) RETURNS BOOLEAN
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
DECLARE v_rentals INT;
|
||||
DECLARE v_out INT;
|
||||
|
||||
#AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
|
||||
#FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
|
||||
|
||||
SELECT COUNT(*) INTO v_rentals
|
||||
FROM rental
|
||||
WHERE inventory_id = p_inventory_id;
|
||||
|
||||
IF v_rentals = 0 THEN
|
||||
RETURN TRUE;
|
||||
END IF;
|
||||
|
||||
SELECT COUNT(rental_id) INTO v_out
|
||||
FROM inventory LEFT JOIN rental USING(inventory_id)
|
||||
WHERE inventory.inventory_id = p_inventory_id
|
||||
AND rental.return_date IS NULL;
|
||||
|
||||
IF v_out > 0 THEN
|
||||
RETURN FALSE;
|
||||
ELSE
|
||||
RETURN TRUE;
|
||||
END IF;
|
||||
END $$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
SET SQL_MODE=@OLD_SQL_MODE;
|
||||
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
|
||||
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
|
||||
|
||||
|
||||
114
tests/init/data/mysql/test_sample.sql
Normal file
114
tests/init/data/mysql/test_sample.sql
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
-- MySQL dump 10.13 Distrib 8.0.16, for Linux (x86_64)
|
||||
|
||||
|
||||
--
|
||||
-- Table structure for table `all_types8`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `all_types`;
|
||||
|
||||
CREATE TABLE `all_types` (
|
||||
`tiny_int` TINYINT NOT NULL,
|
||||
`utiny_int` TINYINT unsigned NOT NULL,
|
||||
|
||||
`small_int` SMALLINT NOT NULL,
|
||||
`usmall_int` SMALLINT unsigned NOT NULL,
|
||||
|
||||
`medium_int` MEDIUMINT NOT NULL,
|
||||
`umedium_int` MEDIUMINT unsigned NOT NULL,
|
||||
|
||||
`int` INT NOT NULL,
|
||||
`uint` INT unsigned NOT NULL,
|
||||
|
||||
`big_int` bigint(20) NOT NULL,
|
||||
`ubig_int` bigint(20) unsigned NOT NULL,
|
||||
|
||||
-- ptr
|
||||
|
||||
`tiny_int_ptr` TINYINT,
|
||||
`utiny_int_ptr` TINYINT unsigned,
|
||||
|
||||
`small_int_ptr` SMALLINT,
|
||||
`usmall_int_ptr` SMALLINT unsigned,
|
||||
|
||||
`medium_int_ptr` MEDIUMINT,
|
||||
`umedium_int_ptr` MEDIUMINT unsigned,
|
||||
|
||||
`int_ptr` INT,
|
||||
`uint_ptr` INT unsigned,
|
||||
|
||||
`big_int_ptr` bigint(20),
|
||||
`ubig_int_ptr` bigint(20) unsigned,
|
||||
|
||||
|
||||
-- floats
|
||||
`decimal` decimal(5, 2) unsigned NOT NULL,
|
||||
`decimal_ptr` decimal(5,2),
|
||||
|
||||
`numeric` numeric(5,2) NOT NULL,
|
||||
`numeric_ptr` numeric(5, 2),
|
||||
|
||||
`float` float NOT NULL,
|
||||
`float_ptr` float,
|
||||
|
||||
`double` double NOT NULL,
|
||||
`double_ptr` double,
|
||||
|
||||
-- bit values
|
||||
|
||||
`bit` bit(10) NOT NULL,
|
||||
`bit_ptr` bit(10),
|
||||
|
||||
-- date and time
|
||||
|
||||
`date` date NOT NULL,
|
||||
`date_ptr` date,
|
||||
|
||||
`date_time` datetime NOT NULL,
|
||||
`date_time_ptr` datetime,
|
||||
|
||||
`timestamp` timestamp NOT NULL,
|
||||
`timestamp_ptr` timestamp,
|
||||
|
||||
`year` year NOT NULL,
|
||||
`year_ptr` year,
|
||||
|
||||
-- strings
|
||||
|
||||
`char` char(20) NOT NULL,
|
||||
`char_ptr` char(20),
|
||||
|
||||
`varchar` varchar(20) NOT NULL,
|
||||
`varchar_ptr` varchar(20),
|
||||
|
||||
`binary` binary(20) NOT NULL,
|
||||
`binary_ptr` binary(20),
|
||||
|
||||
`var_binary` varbinary(20) NOT NULL,
|
||||
`var_binary_ptr` varbinary(20),
|
||||
|
||||
`blob` blob NOT NULL,
|
||||
`blob_ptr` blob,
|
||||
|
||||
`text` text NOT NULL,
|
||||
`text_ptr` text,
|
||||
|
||||
`enum` enum('value1', 'value2', 'value3') NOT NULL,
|
||||
`enum_ptr` enum('value1', 'value2', 'value3'),
|
||||
|
||||
`set` set('s1', 's2', 's3') NOT NULL,
|
||||
`set_ptr` set('s1', 's2', 's3'),
|
||||
|
||||
-- json
|
||||
|
||||
`json` json NOT NULL,
|
||||
`json_ptr` json
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
INSERT INTO `all_types` VALUES
|
||||
(-3,3,-14,14,-150,150,-1600,1600,-17000,17000,-3,3,-14,14,-150,150,-1600,1600,-17000,17000,1.11,1.11,2.22,2.22,3.33,3.33,4.44,4.44,_binary '\0',_binary '\0','2008-07-04','2008-07-04','2011-12-18 13:17:17','2011-12-18 13:17:17','2007-12-31 23:00:01','2007-12-31 23:00:01',2004,2004,'char','char','varchar','varchar',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'varbinary',_binary 'varbinary',_binary 'blob',_binary 'blob','text','text','value1','value1','s1','s2','{\"key1\": \"value1\", \"key2\": \"value2\"}','{\"key1\": \"value1\", \"key2\": \"value2\"}'),
|
||||
(-3,3,-14,14,-150,150,-1600,1600,-17000,17000,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1.11,NULL,2.22,NULL,3.33,NULL,4.44,NULL,_binary '\0',NULL,'2008-07-04',NULL,'2011-12-18 13:17:17',NULL,'2007-12-31 23:00:01',NULL,2004,NULL,'char',NULL,'varchar',NULL,_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',NULL,_binary 'varbinary',NULL,_binary 'blob',NULL,'text',NULL,'value1',NULL,'s1',NULL,'{\"key1\": \"value1\", \"key2\": \"value2\"}',NULL);
|
||||
|
||||
|
||||
|
||||
|
|
@ -2,17 +2,75 @@ package main
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/go-jet/jet/generator/mysql"
|
||||
"github.com/go-jet/jet/generator/postgres"
|
||||
"github.com/go-jet/jet/tests/dbconfig"
|
||||
_ "github.com/lib/pq"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(dbconfig.ConnectString)
|
||||
var testSuite string
|
||||
|
||||
db, err := sql.Open("postgres", dbconfig.ConnectString)
|
||||
func init() {
|
||||
flag.StringVar(&testSuite, "testsuite", "all", "Test suite name (postgres or mysql)")
|
||||
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
if testSuite == "postgres" {
|
||||
initPostgresDB()
|
||||
return
|
||||
}
|
||||
|
||||
if testSuite == "mysql" {
|
||||
initMySQLDB()
|
||||
return
|
||||
}
|
||||
|
||||
initMySQLDB()
|
||||
initPostgresDB()
|
||||
}
|
||||
|
||||
func initMySQLDB() {
|
||||
|
||||
mySQLDBs := []string{
|
||||
"test_sample",
|
||||
}
|
||||
|
||||
for _, dbName := range mySQLDBs {
|
||||
cmdLine := fmt.Sprintf("mysql -u %s -p%s %s < %s",
|
||||
dbconfig.MySQLUser, dbconfig.MySQLPassword, dbName, "./init/data/mysql/"+dbName+".sql")
|
||||
cmd := exec.Command("sh", "-c", cmdLine)
|
||||
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
|
||||
err := cmd.Run()
|
||||
panicOnError(err)
|
||||
|
||||
err = mysql.Generate("./.gentestdata/mysql", mysql.DBConnection{
|
||||
Host: dbconfig.MySqLHost,
|
||||
Port: dbconfig.MySQLPort,
|
||||
User: dbconfig.MySQLUser,
|
||||
Password: dbconfig.MySQLPassword,
|
||||
//SslMode:
|
||||
//Params
|
||||
DBName: dbName,
|
||||
})
|
||||
|
||||
panicOnError(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func initPostgresDB() {
|
||||
db, err := sql.Open("postgres", dbconfig.PostgresConnectString)
|
||||
if err != nil {
|
||||
panic("Failed to connect to test db")
|
||||
}
|
||||
|
|
@ -29,13 +87,8 @@ func main() {
|
|||
}
|
||||
|
||||
for _, schemaName := range schemaNames {
|
||||
testSampleSql, err := ioutil.ReadFile("./init/data/" + schemaName + ".sql")
|
||||
|
||||
panicOnError(err)
|
||||
|
||||
_, err = db.Exec(string(testSampleSql))
|
||||
|
||||
panicOnError(err)
|
||||
execFile(db, "./init/data/postgres/"+schemaName+".sql")
|
||||
|
||||
err = postgres.Generate("./.gentestdata", postgres.DBConnection{
|
||||
Host: dbconfig.Host,
|
||||
|
|
@ -46,11 +99,18 @@ func main() {
|
|||
SchemaName: schemaName,
|
||||
SslMode: "disable",
|
||||
})
|
||||
|
||||
panicOnError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func execFile(db *sql.DB, sqlFilePath string) {
|
||||
testSampleSql, err := ioutil.ReadFile(sqlFilePath)
|
||||
panicOnError(err)
|
||||
|
||||
_, err = db.Exec(string(testSampleSql))
|
||||
panicOnError(err)
|
||||
}
|
||||
|
||||
func panicOnError(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package tests
|
|||
import (
|
||||
"context"
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"gotest.tools/assert"
|
||||
|
|
@ -30,7 +31,7 @@ RETURNING link.id AS "link.id",
|
|||
VALUES(102, "http://www.yahoo.com", "Yahoo", nil).
|
||||
RETURNING(Link.AllColumns)
|
||||
|
||||
assertStatementSql(t, insertQuery, expectedSQL,
|
||||
testutils.AssertStatementSql(t, insertQuery, expectedSQL,
|
||||
100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
|
||||
101, "http://www.google.com", "Google",
|
||||
102, "http://www.yahoo.com", "Yahoo", nil)
|
||||
|
|
@ -84,7 +85,7 @@ INSERT INTO test_sample.link VALUES
|
|||
stmt := Link.INSERT().
|
||||
VALUES(100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT)
|
||||
|
||||
assertStatementSql(t, stmt, expectedSQL,
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL,
|
||||
100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial")
|
||||
|
||||
assertExec(t, stmt, 1)
|
||||
|
|
@ -106,7 +107,7 @@ INSERT INTO test_sample.link (url, name) VALUES
|
|||
INSERT(Link.URL, Link.Name).
|
||||
MODEL(linkData)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, "http://www.duckduckgo.com", "Duck Duck go")
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, "http://www.duckduckgo.com", "Duck Duck go")
|
||||
|
||||
assertExec(t, query, 1)
|
||||
}
|
||||
|
|
@ -128,7 +129,7 @@ INSERT INTO test_sample.link VALUES
|
|||
INSERT().
|
||||
MODEL(linkData)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, int32(1000), "http://www.duckduckgo.com", "Duck Duck go", nil)
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int32(1000), "http://www.duckduckgo.com", "Duck Duck go", nil)
|
||||
|
||||
assertExec(t, query, 1)
|
||||
}
|
||||
|
|
@ -160,7 +161,7 @@ INSERT INTO test_sample.link (url, name) VALUES
|
|||
INSERT(Link.URL, Link.Name).
|
||||
MODELS([]model.Link{tutorial, google, yahoo})
|
||||
|
||||
assertStatementSql(t, stmt, expectedSQL,
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL,
|
||||
"http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
|
||||
"http://www.google.com", "Google",
|
||||
"http://www.yahoo.com", "Yahoo")
|
||||
|
|
@ -193,7 +194,7 @@ INSERT INTO test_sample.link (url, name, description) VALUES
|
|||
MODEL(google).
|
||||
MODELS([]model.Link{google, yahoo})
|
||||
|
||||
assertStatementSql(t, stmt, expectedSQL,
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL,
|
||||
"http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
|
||||
"http://www.google.com", "Google", nil,
|
||||
"http://www.google.com", "Google", nil,
|
||||
|
|
@ -230,7 +231,7 @@ RETURNING link.id AS "link.id",
|
|||
).
|
||||
RETURNING(Link.AllColumns)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, int64(0))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(0))
|
||||
|
||||
dest := []model.Link{}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package tests
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -28,7 +29,7 @@ LOCK TABLE dvds.address IN`
|
|||
for _, lockMode := range testData {
|
||||
query := Address.LOCK().IN(lockMode)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL+" "+string(lockMode)+" MODE;\n")
|
||||
testutils.AssertStatementSql(t, query, expectedSQL+" "+string(lockMode)+" MODE;\n")
|
||||
|
||||
tx, _ := db.Begin()
|
||||
|
||||
|
|
@ -44,7 +45,7 @@ LOCK TABLE dvds.address IN`
|
|||
for _, lockMode := range testData {
|
||||
query := Address.LOCK().IN(lockMode).NOWAIT()
|
||||
|
||||
assertStatementSql(t, query, expectedSQL+" "+string(lockMode)+" MODE NOWAIT;\n")
|
||||
testutils.AssertStatementSql(t, query, expectedSQL+" "+string(lockMode)+" MODE NOWAIT;\n")
|
||||
|
||||
tx, _ := db.Begin()
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ func TestMain(m *testing.M) {
|
|||
defer profile.Start().Stop()
|
||||
|
||||
var err error
|
||||
db, err = sql.Open("postgres", dbconfig.ConnectString)
|
||||
db, err = sql.Open("postgres", dbconfig.PostgresConnectString)
|
||||
if err != nil {
|
||||
panic("Failed to connect to test db")
|
||||
}
|
||||
|
|
@ -185,6 +185,7 @@ package table
|
|||
|
||||
import (
|
||||
"github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/postgres"
|
||||
)
|
||||
|
||||
var Actor = newActorTable()
|
||||
|
|
@ -193,10 +194,10 @@ type ActorTable struct {
|
|||
jet.Table
|
||||
|
||||
//Columns
|
||||
ActorID jet.ColumnInteger
|
||||
FirstName jet.ColumnString
|
||||
LastName jet.ColumnString
|
||||
LastUpdate jet.ColumnTimestamp
|
||||
ActorID postgres.ColumnInteger
|
||||
FirstName postgres.ColumnString
|
||||
LastName postgres.ColumnString
|
||||
LastUpdate postgres.ColumnTimestamp
|
||||
|
||||
AllColumns jet.ColumnList
|
||||
MutableColumns jet.ColumnList
|
||||
|
|
@ -213,14 +214,14 @@ func (a *ActorTable) AS(alias string) *ActorTable {
|
|||
|
||||
func newActorTable() *ActorTable {
|
||||
var (
|
||||
ActorIDColumn = jet.IntegerColumn("actor_id")
|
||||
FirstNameColumn = jet.StringColumn("first_name")
|
||||
LastNameColumn = jet.StringColumn("last_name")
|
||||
LastUpdateColumn = jet.TimestampColumn("last_update")
|
||||
ActorIDColumn = postgres.IntegerColumn("actor_id")
|
||||
FirstNameColumn = postgres.StringColumn("first_name")
|
||||
LastNameColumn = postgres.StringColumn("last_name")
|
||||
LastUpdateColumn = postgres.TimestampColumn("last_update")
|
||||
)
|
||||
|
||||
return &ActorTable{
|
||||
Table: jet.NewTable("dvds", "actor", ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn),
|
||||
Table: jet.NewTable(jet.PostgreSQL, "dvds", "actor", ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn),
|
||||
|
||||
//Columns
|
||||
ActorID: ActorIDColumn,
|
||||
|
|
|
|||
33
tests/mysql/mysql_test.go
Normal file
33
tests/mysql/mysql_test.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/go-jet/jet/tests/dbconfig"
|
||||
|
||||
//_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/ziutek/mymysql/godrv"
|
||||
|
||||
"github.com/pkg/profile"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
defer profile.Start().Stop()
|
||||
|
||||
fmt.Println(dbconfig.MySQLConnectionString)
|
||||
|
||||
var err error
|
||||
db, err = sql.Open("mysql", "jet:jet@tcp(localhost:3306)/")
|
||||
if err != nil {
|
||||
panic("Failed to connect to test db" + err.Error())
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
ret := m.Run()
|
||||
|
||||
os.Exit(ret)
|
||||
}
|
||||
45
tests/mysql/sakila_test.go
Normal file
45
tests/mysql/sakila_test.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
. "github.com/go-jet/jet/mysql"
|
||||
"gotest.tools/assert"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-jet/jet/tests/.gentestdata/sakila/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/sakila/table"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSelect_ScanToStruct(t *testing.T) {
|
||||
expectedSQL := `
|
||||
SELECT DISTINCT actor.actor_id AS "actor.actor_id",
|
||||
actor.first_name AS "actor.first_name",
|
||||
actor.last_name AS "actor.last_name",
|
||||
actor.last_update AS "actor.last_update"
|
||||
FROM sakila.actor
|
||||
WHERE actor.actor_id = 1;
|
||||
`
|
||||
spew.Dump(reflect.TypeOf(db.Driver()).String())
|
||||
|
||||
query := Actor.
|
||||
SELECT(Actor.AllColumns).
|
||||
DISTINCT().
|
||||
WHERE(Actor.ActorID.EQ(Int(1)))
|
||||
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(1))
|
||||
|
||||
actor := model.Actor{}
|
||||
err := query.Query(db, &actor)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.DeepEqual(t, actor, model.Actor{
|
||||
ActorID: 1,
|
||||
FirstName: "PENELOPE",
|
||||
LastName: "GUINESS",
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 04:34:33", 2),
|
||||
})
|
||||
}
|
||||
145
tests/mysql/sample_test.go
Normal file
145
tests/mysql/sample_test.go
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
package mysql
|
||||
|
||||
import (
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAllTypes(t *testing.T) {
|
||||
|
||||
dest := []model.AllTypes{}
|
||||
|
||||
err := AllTypes.
|
||||
SELECT(AllTypes.AllColumns).
|
||||
LIMIT(2).
|
||||
Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
//testutils.JsonPrint(dest)
|
||||
testutils.AssertJSON(t, dest, allTypesJson)
|
||||
}
|
||||
|
||||
var allTypesJson = `
|
||||
[
|
||||
{
|
||||
"TinyInt": -3,
|
||||
"UtinyInt": 3,
|
||||
"SmallInt": -14,
|
||||
"UsmallInt": 14,
|
||||
"MediumInt": -150,
|
||||
"UmediumInt": 150,
|
||||
"Int": -1600,
|
||||
"Uint": 1600,
|
||||
"BigInt": -17000,
|
||||
"UbigInt": 17000,
|
||||
"TinyIntPtr": -3,
|
||||
"UtinyIntPtr": 3,
|
||||
"SmallIntPtr": -14,
|
||||
"UsmallIntPtr": 14,
|
||||
"MediumIntPtr": -150,
|
||||
"UmediumIntPtr": 150,
|
||||
"IntPtr": -1600,
|
||||
"UintPtr": 1600,
|
||||
"BigIntPtr": -17000,
|
||||
"UbigIntPtr": 17000,
|
||||
"Decimal": 1.11,
|
||||
"DecimalPtr": 1.11,
|
||||
"Numeric": 2.22,
|
||||
"NumericPtr": 2.22,
|
||||
"Float": 3.33,
|
||||
"FloatPtr": 3.33,
|
||||
"Double": 4.44,
|
||||
"DoublePtr": 4.44,
|
||||
"Bit": "\u0000\u0003",
|
||||
"BitPtr": "\u0000\u0003",
|
||||
"Date": "2008-07-04T00:00:00Z",
|
||||
"DatePtr": "2008-07-04T00:00:00Z",
|
||||
"DateTime": "2011-12-18T13:17:17Z",
|
||||
"DateTimePtr": "2011-12-18T13:17:17Z",
|
||||
"Timestamp": "2007-12-31T23:00:01Z",
|
||||
"TimestampPtr": "2007-12-31T23:00:01Z",
|
||||
"Year": 2004,
|
||||
"YearPtr": 2004,
|
||||
"Char": "char",
|
||||
"CharPtr": "char",
|
||||
"Varchar": "varchar",
|
||||
"VarcharPtr": "varchar",
|
||||
"Binary": "YmluYXJ5AAAAAAAAAAAAAAAAAAA=",
|
||||
"BinaryPtr": "YmluYXJ5AAAAAAAAAAAAAAAAAAA=",
|
||||
"VarBinary": "dmFyYmluYXJ5",
|
||||
"VarBinaryPtr": "dmFyYmluYXJ5",
|
||||
"Blob": "YmxvYg==",
|
||||
"BlobPtr": "YmxvYg==",
|
||||
"Text": "text",
|
||||
"TextPtr": "text",
|
||||
"Enum": "value1",
|
||||
"EnumPtr": "value1",
|
||||
"Set": "s1",
|
||||
"SetPtr": "s2",
|
||||
"JSON": "{\"key1\": \"value1\", \"key2\": \"value2\"}",
|
||||
"JSONPtr": "{\"key1\": \"value1\", \"key2\": \"value2\"}"
|
||||
},
|
||||
{
|
||||
"TinyInt": -3,
|
||||
"UtinyInt": 3,
|
||||
"SmallInt": -14,
|
||||
"UsmallInt": 14,
|
||||
"MediumInt": -150,
|
||||
"UmediumInt": 150,
|
||||
"Int": -1600,
|
||||
"Uint": 1600,
|
||||
"BigInt": -17000,
|
||||
"UbigInt": 17000,
|
||||
"TinyIntPtr": null,
|
||||
"UtinyIntPtr": null,
|
||||
"SmallIntPtr": null,
|
||||
"UsmallIntPtr": null,
|
||||
"MediumIntPtr": null,
|
||||
"UmediumIntPtr": null,
|
||||
"IntPtr": null,
|
||||
"UintPtr": null,
|
||||
"BigIntPtr": null,
|
||||
"UbigIntPtr": null,
|
||||
"Decimal": 1.11,
|
||||
"DecimalPtr": null,
|
||||
"Numeric": 2.22,
|
||||
"NumericPtr": null,
|
||||
"Float": 3.33,
|
||||
"FloatPtr": null,
|
||||
"Double": 4.44,
|
||||
"DoublePtr": null,
|
||||
"Bit": "\u0000\u0003",
|
||||
"BitPtr": null,
|
||||
"Date": "2008-07-04T00:00:00Z",
|
||||
"DatePtr": null,
|
||||
"DateTime": "2011-12-18T13:17:17Z",
|
||||
"DateTimePtr": null,
|
||||
"Timestamp": "2007-12-31T23:00:01Z",
|
||||
"TimestampPtr": null,
|
||||
"Year": 2004,
|
||||
"YearPtr": null,
|
||||
"Char": "char",
|
||||
"CharPtr": null,
|
||||
"Varchar": "varchar",
|
||||
"VarcharPtr": null,
|
||||
"Binary": "YmluYXJ5AAAAAAAAAAAAAAAAAAA=",
|
||||
"BinaryPtr": null,
|
||||
"VarBinary": "dmFyYmluYXJ5",
|
||||
"VarBinaryPtr": null,
|
||||
"Blob": "YmxvYg==",
|
||||
"BlobPtr": null,
|
||||
"Text": "text",
|
||||
"TextPtr": null,
|
||||
"Enum": "value1",
|
||||
"EnumPtr": null,
|
||||
"Set": "s1",
|
||||
"SetPtr": null,
|
||||
"JSON": "{\"key1\": \"value1\", \"key2\": \"value2\"}",
|
||||
"JSONPtr": null
|
||||
}
|
||||
]
|
||||
`
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/northwind/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/northwind/table"
|
||||
"gotest.tools/assert"
|
||||
|
|
@ -61,5 +62,5 @@ func TestNorthwindJoinEverything(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/northwind-all.json", dest)
|
||||
assertJSONFile(t, "./testdata/northwind-all.json", dest)
|
||||
testutils.AssertJSONFile(t, "./testdata/northwind-all.json", dest)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package tests
|
|||
|
||||
import (
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"github.com/google/uuid"
|
||||
|
|
@ -14,7 +15,7 @@ func TestUUIDType(t *testing.T) {
|
|||
SELECT(AllTypes.UUID, AllTypes.UUIDPtr).
|
||||
WHERE(AllTypes.UUID.EQ(String("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11")))
|
||||
|
||||
assertStatementSql(t, query, `
|
||||
testutils.AssertStatementSql(t, query, `
|
||||
SELECT all_types.uuid AS "all_types.uuid",
|
||||
all_types.uuid_ptr AS "all_types.uuid_ptr"
|
||||
FROM test_sample.all_types
|
||||
|
|
@ -26,14 +27,14 @@ WHERE all_types.uuid = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11';
|
|||
err := query.Query(db, &result)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, result.UUID, uuid.MustParse("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"))
|
||||
assert.DeepEqual(t, result.UUIDPtr, uuidPtr("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"))
|
||||
assert.DeepEqual(t, result.UUIDPtr, UUIDPtr("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"))
|
||||
}
|
||||
|
||||
func TestEnumType(t *testing.T) {
|
||||
query := Person.
|
||||
SELECT(Person.AllColumns)
|
||||
|
||||
assertStatementSql(t, query, `
|
||||
testutils.AssertStatementSql(t, query, `
|
||||
SELECT person.person_id AS "person.person_id",
|
||||
person.first_name AS "person.first_name",
|
||||
person.last_name AS "person.last_name",
|
||||
|
|
@ -46,7 +47,7 @@ FROM test_sample.person;
|
|||
err := query.Query(db, &result)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assertJSON(t, result, `
|
||||
testutils.AssertJSON(t, result, `
|
||||
[
|
||||
{
|
||||
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6",
|
||||
|
|
@ -97,7 +98,7 @@ ORDER BY employee.employee_id;
|
|||
).
|
||||
ORDER_BY(Employee.EmployeeID)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL)
|
||||
testutils.AssertStatementSql(t, query, expectedSQL)
|
||||
|
||||
type Manager model.Employee
|
||||
|
||||
|
|
@ -115,7 +116,7 @@ ORDER BY employee.employee_id;
|
|||
EmployeeID: 1,
|
||||
FirstName: "Windy",
|
||||
LastName: "Hays",
|
||||
EmploymentDate: timestampWithTimeZone("1999-01-08 04:05:06.1 +0100 CET", 1),
|
||||
EmploymentDate: TimestampWithTimeZone("1999-01-08 04:05:06.1 +0100 CET", 1),
|
||||
ManagerID: nil,
|
||||
})
|
||||
|
||||
|
|
@ -125,15 +126,15 @@ ORDER BY employee.employee_id;
|
|||
EmployeeID: 8,
|
||||
FirstName: "Salley",
|
||||
LastName: "Lester",
|
||||
EmploymentDate: timestampWithTimeZone("1999-01-08 04:05:06 +0100 CET", 1),
|
||||
ManagerID: int32Ptr(3),
|
||||
EmploymentDate: TimestampWithTimeZone("1999-01-08 04:05:06 +0100 CET", 1),
|
||||
ManagerID: Int32Ptr(3),
|
||||
})
|
||||
}
|
||||
|
||||
func TestWierdNamesTable(t *testing.T) {
|
||||
stmt := WeirdNamesTable.SELECT(WeirdNamesTable.AllColumns)
|
||||
|
||||
assertStatementSql(t, stmt, `
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT "WEIRD NAMES TABLE".weird_column_name1 AS "WEIRD NAMES TABLE.weird_column_name1",
|
||||
"WEIRD NAMES TABLE"."Weird_Column_Name2" AS "WEIRD NAMES TABLE.Weird_Column_Name2",
|
||||
"WEIRD NAMES TABLE"."wEiRd_cOluMn_nAmE3" AS "WEIRD NAMES TABLE.wEiRd_cOluMn_nAmE3",
|
||||
|
|
@ -168,7 +169,7 @@ FROM test_sample."WEIRD NAMES TABLE";
|
|||
WeirdColumnName5: "Doe",
|
||||
WeirdColumnName6: "Doe",
|
||||
WeirdColumnName7: "Doe",
|
||||
Weirdcolumnname8: stringPtr("Doe"),
|
||||
Weirdcolumnname8: StringPtr("Doe"),
|
||||
WeirdColName9: "Doe",
|
||||
WeirdColuName10: "Doe",
|
||||
WeirdColuName11: "Doe",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package tests
|
|||
|
||||
import (
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/table"
|
||||
"github.com/google/uuid"
|
||||
|
|
@ -158,7 +159,7 @@ func TestScanToStruct(t *testing.T) {
|
|||
assert.Equal(t, *dest.StoreID, int16(1))
|
||||
})
|
||||
|
||||
t.Run("type mismatch base type", func(t *testing.T) {
|
||||
t.Run("type convert int32 to int", func(t *testing.T) {
|
||||
type Inventory struct {
|
||||
InventoryID int
|
||||
FilmID string
|
||||
|
|
@ -168,7 +169,7 @@ func TestScanToStruct(t *testing.T) {
|
|||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.Error(t, err, `jet: can't set int32 to int, at struct field: InventoryID int of type tests.Inventory. `)
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
|
||||
t.Run("type mismatch scanner type", func(t *testing.T) {
|
||||
|
|
@ -483,10 +484,10 @@ func TestScanToSlice(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assert.DeepEqual(t, dest[0].Film, film1)
|
||||
assert.DeepEqual(t, dest[0].IDs, []*int32{int32Ptr(1), int32Ptr(2), int32Ptr(3), int32Ptr(4),
|
||||
int32Ptr(5), int32Ptr(6), int32Ptr(7), int32Ptr(8)})
|
||||
assert.DeepEqual(t, dest[0].IDs, []*int32{Int32Ptr(1), Int32Ptr(2), Int32Ptr(3), Int32Ptr(4),
|
||||
Int32Ptr(5), Int32Ptr(6), Int32Ptr(7), Int32Ptr(8)})
|
||||
assert.DeepEqual(t, dest[1].Film, film2)
|
||||
assert.DeepEqual(t, dest[1].IDs, []*int32{int32Ptr(9), int32Ptr(10)})
|
||||
assert.DeepEqual(t, dest[1].IDs, []*int32{Int32Ptr(9), Int32Ptr(10)})
|
||||
})
|
||||
|
||||
t.Run("complex struct 1", func(t *testing.T) {
|
||||
|
|
@ -677,23 +678,23 @@ func TestScanToSlice(t *testing.T) {
|
|||
var address256 = model.Address{
|
||||
AddressID: 256,
|
||||
Address: "1497 Yuzhou Drive",
|
||||
Address2: stringPtr(""),
|
||||
Address2: StringPtr(""),
|
||||
District: "England",
|
||||
CityID: 312,
|
||||
PostalCode: stringPtr("3433"),
|
||||
PostalCode: StringPtr("3433"),
|
||||
Phone: "246810237916",
|
||||
LastUpdate: *timestampWithoutTimeZone("2006-02-15 09:45:30", 0),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:45:30", 0),
|
||||
}
|
||||
|
||||
var addres517 = model.Address{
|
||||
AddressID: 517,
|
||||
Address: "548 Uruapan Street",
|
||||
Address2: stringPtr(""),
|
||||
Address2: StringPtr(""),
|
||||
District: "Ontario",
|
||||
CityID: 312,
|
||||
PostalCode: stringPtr("35653"),
|
||||
PostalCode: StringPtr("35653"),
|
||||
Phone: "879347453467",
|
||||
LastUpdate: *timestampWithoutTimeZone("2006-02-15 09:45:30", 0),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:45:30", 0),
|
||||
}
|
||||
|
||||
var customer256 = model.Customer{
|
||||
|
|
@ -701,12 +702,12 @@ var customer256 = model.Customer{
|
|||
StoreID: 2,
|
||||
FirstName: "Mattie",
|
||||
LastName: "Hoffman",
|
||||
Email: stringPtr("mattie.hoffman@sakilacustomer.org"),
|
||||
Email: StringPtr("mattie.hoffman@sakilacustomer.org"),
|
||||
AddressID: 256,
|
||||
Activebool: true,
|
||||
CreateDate: *timestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: timestampWithoutTimeZone("2013-05-26 14:49:45.738", 0),
|
||||
Active: int32Ptr(1),
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 0),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
|
||||
var customer512 = model.Customer{
|
||||
|
|
@ -714,70 +715,70 @@ var customer512 = model.Customer{
|
|||
StoreID: 1,
|
||||
FirstName: "Cecil",
|
||||
LastName: "Vines",
|
||||
Email: stringPtr("cecil.vines@sakilacustomer.org"),
|
||||
Email: StringPtr("cecil.vines@sakilacustomer.org"),
|
||||
AddressID: 517,
|
||||
Activebool: true,
|
||||
CreateDate: *timestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: timestampWithoutTimeZone("2013-05-26 14:49:45.738", 0),
|
||||
Active: int32Ptr(1),
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 0),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
|
||||
var countryUk = model.Country{
|
||||
CountryID: 102,
|
||||
Country: "United Kingdom",
|
||||
LastUpdate: *timestampWithoutTimeZone("2006-02-15 09:44:00", 0),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:44:00", 0),
|
||||
}
|
||||
|
||||
var cityLondon = model.City{
|
||||
CityID: 312,
|
||||
City: "London",
|
||||
CountryID: 102,
|
||||
LastUpdate: *timestampWithoutTimeZone("2006-02-15 09:45:25", 0),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:45:25", 0),
|
||||
}
|
||||
|
||||
var inventory1 = model.Inventory{
|
||||
InventoryID: 1,
|
||||
FilmID: 1,
|
||||
StoreID: 1,
|
||||
LastUpdate: *timestampWithoutTimeZone("2006-02-15 10:09:17", 0),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 10:09:17", 0),
|
||||
}
|
||||
|
||||
var inventory2 = model.Inventory{
|
||||
InventoryID: 2,
|
||||
FilmID: 1,
|
||||
StoreID: 1,
|
||||
LastUpdate: *timestampWithoutTimeZone("2006-02-15 10:09:17", 0),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 10:09:17", 0),
|
||||
}
|
||||
|
||||
var film1 = model.Film{
|
||||
FilmID: 1,
|
||||
Title: "Academy Dinosaur",
|
||||
Description: stringPtr("A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies"),
|
||||
ReleaseYear: int32Ptr(2006),
|
||||
Description: StringPtr("A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies"),
|
||||
ReleaseYear: Int32Ptr(2006),
|
||||
LanguageID: 1,
|
||||
RentalDuration: 6,
|
||||
RentalRate: 0.99,
|
||||
Length: int16Ptr(86),
|
||||
Length: Int16Ptr(86),
|
||||
ReplacementCost: 20.99,
|
||||
Rating: &pgRating,
|
||||
LastUpdate: *timestampWithoutTimeZone("2013-05-26 14:50:58.951", 3),
|
||||
SpecialFeatures: stringPtr("{\"Deleted Scenes\",\"Behind the Scenes\"}"),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2013-05-26 14:50:58.951", 3),
|
||||
SpecialFeatures: StringPtr("{\"Deleted Scenes\",\"Behind the Scenes\"}"),
|
||||
Fulltext: "'academi':1 'battl':15 'canadian':20 'dinosaur':2 'drama':5 'epic':4 'feminist':8 'mad':11 'must':14 'rocki':21 'scientist':12 'teacher':17",
|
||||
}
|
||||
|
||||
var film2 = model.Film{
|
||||
FilmID: 2,
|
||||
Title: "Ace Goldfinger",
|
||||
Description: stringPtr("A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China"),
|
||||
ReleaseYear: int32Ptr(2006),
|
||||
Description: StringPtr("A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China"),
|
||||
ReleaseYear: Int32Ptr(2006),
|
||||
LanguageID: 1,
|
||||
RentalDuration: 3,
|
||||
RentalRate: 4.99,
|
||||
Length: int16Ptr(48),
|
||||
Length: Int16Ptr(48),
|
||||
ReplacementCost: 12.99,
|
||||
Rating: &gRating,
|
||||
LastUpdate: *timestampWithoutTimeZone("2013-05-26 14:50:58.951", 3),
|
||||
SpecialFeatures: stringPtr(`{Trailers,"Deleted Scenes"}`),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2013-05-26 14:50:58.951", 3),
|
||||
SpecialFeatures: StringPtr(`{Trailers,"Deleted Scenes"}`),
|
||||
Fulltext: `'ace':1 'administr':9 'ancient':19 'astound':4 'car':17 'china':20 'databas':8 'epistl':5 'explor':12 'find':15 'goldfing':2 'must':14`,
|
||||
}
|
||||
|
||||
|
|
@ -785,7 +786,7 @@ var store1 = model.Store{
|
|||
StoreID: 1,
|
||||
ManagerStaffID: 1,
|
||||
AddressID: 1,
|
||||
LastUpdate: *timestampWithoutTimeZone("2006-02-15 09:57:12", 0),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:57:12", 0),
|
||||
}
|
||||
|
||||
var pgRating = model.MpaaRating_Pg
|
||||
|
|
@ -794,5 +795,5 @@ var gRating = model.MpaaRating_G
|
|||
var language1 = model.Language{
|
||||
LanguageID: 1,
|
||||
Name: "English ",
|
||||
LastUpdate: *timestampWithoutTimeZone("2006-02-15 10:02:19", 0),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 10:02:19", 0),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package tests
|
|||
|
||||
import (
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/enum"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/table"
|
||||
|
|
@ -24,7 +25,7 @@ WHERE actor.actor_id = 1;
|
|||
DISTINCT().
|
||||
WHERE(Actor.ActorID.EQ(Int(1)))
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, int64(1))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(1))
|
||||
|
||||
actor := model.Actor{}
|
||||
err := query.Query(db, &actor)
|
||||
|
|
@ -35,7 +36,7 @@ WHERE actor.actor_id = 1;
|
|||
ActorID: 1,
|
||||
FirstName: "Penelope",
|
||||
LastName: "Guiness",
|
||||
LastUpdate: *timestampWithoutTimeZone("2013-05-26 14:47:57.62", 2),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2013-05-26 14:47:57.62", 2),
|
||||
}
|
||||
|
||||
assert.DeepEqual(t, actor, expectedActor)
|
||||
|
|
@ -74,7 +75,7 @@ LIMIT 30;
|
|||
ORDER_BY(Payment.PaymentID.ASC()).
|
||||
LIMIT(30)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, int64(30))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(30))
|
||||
|
||||
dest := []model.Payment{}
|
||||
|
||||
|
|
@ -103,7 +104,7 @@ ORDER BY customer.customer_id ASC;
|
|||
|
||||
query := Customer.SELECT(Customer.AllColumns).ORDER_BY(Customer.CustomerID.ASC())
|
||||
|
||||
assertStatementSql(t, query, expectedSQL)
|
||||
testutils.AssertStatementSql(t, query, expectedSQL)
|
||||
|
||||
err := query.Query(db, &customers)
|
||||
assert.NilError(t, err)
|
||||
|
|
@ -156,7 +157,7 @@ LIMIT 12;
|
|||
).
|
||||
LIMIT(12)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, int64(1), int64(1), int64(10), int64(1), int64(2), int64(1), int64(12))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(1), int64(1), int64(10), int64(1), int64(2), int64(1), int64(12))
|
||||
}
|
||||
|
||||
func TestJoinQueryStruct(t *testing.T) {
|
||||
|
|
@ -224,7 +225,7 @@ LIMIT 1000;
|
|||
ORDER_BY(Film.FilmID.ASC()).
|
||||
LIMIT(1000)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, int64(1000))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(1000))
|
||||
|
||||
var languageActorFilm []struct {
|
||||
model.Language
|
||||
|
|
@ -290,7 +291,7 @@ LIMIT 15;
|
|||
WHERE(Film.Rating.EQ(enum.MpaaRating.Nc17)).
|
||||
LIMIT(15)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, int64(15))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(15))
|
||||
|
||||
err := query.Query(db, &filmsPerLanguage)
|
||||
|
||||
|
|
@ -325,7 +326,7 @@ func TestExecution1(t *testing.T) {
|
|||
WHERE(City.City.EQ(String("London")).OR(City.City.EQ(String("York")))).
|
||||
ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID)
|
||||
|
||||
assertStatementSql(t, stmt, `
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT city.city_id AS "city.city_id",
|
||||
city.city AS "city.city",
|
||||
address.address_id AS "address.address_id",
|
||||
|
|
@ -399,7 +400,7 @@ func TestExecution2(t *testing.T) {
|
|||
WHERE(City.City.EQ(String("London")).OR(City.City.EQ(String("York")))).
|
||||
ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID)
|
||||
|
||||
assertStatementSql(t, stmt, `
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT city.city_id AS "my_city.id",
|
||||
city.city AS "myCity.Name",
|
||||
address.address_id AS "My_Address.id",
|
||||
|
|
@ -457,7 +458,7 @@ func TestExecution3(t *testing.T) {
|
|||
WHERE(City.City.EQ(String("London")).OR(City.City.EQ(String("York")))).
|
||||
ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID)
|
||||
|
||||
assertStatementSql(t, stmt, `
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT city.city_id AS "city_id",
|
||||
city.city AS "city_name",
|
||||
customer.customer_id AS "customer_id",
|
||||
|
|
@ -514,7 +515,7 @@ func TestExecution4(t *testing.T) {
|
|||
WHERE(City.City.EQ(String("London")).OR(City.City.EQ(String("York")))).
|
||||
ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID)
|
||||
|
||||
assertStatementSql(t, stmt, `
|
||||
testutils.AssertStatementSql(t, stmt, `
|
||||
SELECT city.city_id AS "city.city_id",
|
||||
city.city AS "city.city",
|
||||
customer.customer_id AS "customer.customer_id",
|
||||
|
|
@ -532,7 +533,7 @@ ORDER BY city.city_id, address.address_id, customer.customer_id;
|
|||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assertJSON(t, dest, `
|
||||
testutils.AssertJSON(t, dest, `
|
||||
[
|
||||
{
|
||||
"CityID": 312,
|
||||
|
|
@ -685,7 +686,7 @@ ORDER BY customer.customer_id ASC;
|
|||
SELECT(Customer.AllColumns, Address.AllColumns).
|
||||
ORDER_BY(Customer.CustomerID.ASC())
|
||||
|
||||
assertStatementSql(t, query, expectedSQL)
|
||||
testutils.AssertStatementSql(t, query, expectedSQL)
|
||||
|
||||
allCustomersAndAddress := []struct {
|
||||
Address *model.Address
|
||||
|
|
@ -738,7 +739,7 @@ LIMIT 1000;
|
|||
ORDER_BY(Customer.CustomerID.ASC()).
|
||||
LIMIT(1000)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, int64(1000))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(1000))
|
||||
|
||||
var customerAddresCrosJoined []struct {
|
||||
model.Customer
|
||||
|
|
@ -793,7 +794,7 @@ ORDER BY f1.film_id ASC;
|
|||
SELECT(f1.AllColumns, f2.AllColumns).
|
||||
ORDER_BY(f1.FilmID.ASC())
|
||||
|
||||
assertStatementSql(t, query, expectedSQL)
|
||||
testutils.AssertStatementSql(t, query, expectedSQL)
|
||||
|
||||
type F1 model.Film
|
||||
type F2 model.Film
|
||||
|
|
@ -835,7 +836,7 @@ LIMIT 1000;
|
|||
ORDER_BY(f1.Length.ASC(), f1.Title.ASC(), f2.Title.ASC()).
|
||||
LIMIT(1000)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, int64(1000))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(1000))
|
||||
|
||||
type thesameLengthFilms struct {
|
||||
Title1 string
|
||||
|
|
@ -897,7 +898,7 @@ FROM dvds.actor
|
|||
rRatingFilms.AllColumns(),
|
||||
)
|
||||
|
||||
assertStatementSql(t, query, expectedQuery)
|
||||
testutils.AssertStatementSql(t, query, expectedQuery)
|
||||
|
||||
dest := []model.Actor{}
|
||||
|
||||
|
|
@ -915,7 +916,7 @@ FROM dvds.film;
|
|||
MAXf(Film.RentalRate).AS("max_film_rate"),
|
||||
)
|
||||
|
||||
assertStatementSql(t, query, expectedQuery)
|
||||
testutils.AssertStatementSql(t, query, expectedQuery)
|
||||
|
||||
ret := struct {
|
||||
MaxFilmRate float64
|
||||
|
|
@ -960,7 +961,7 @@ ORDER BY film.film_id ASC;
|
|||
WHERE(Film.RentalRate.EQ(maxFilmRentalRate)).
|
||||
ORDER_BY(Film.FilmID.ASC())
|
||||
|
||||
assertStatementSql(t, query, expectedSQL)
|
||||
testutils.AssertStatementSql(t, query, expectedSQL)
|
||||
|
||||
maxRentalRateFilms := []model.Film{}
|
||||
err := query.Query(db, &maxRentalRateFilms)
|
||||
|
|
@ -974,16 +975,16 @@ ORDER BY film.film_id ASC;
|
|||
assert.DeepEqual(t, maxRentalRateFilms[0], model.Film{
|
||||
FilmID: 2,
|
||||
Title: "Ace Goldfinger",
|
||||
Description: stringPtr("A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China"),
|
||||
ReleaseYear: int32Ptr(2006),
|
||||
Description: StringPtr("A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China"),
|
||||
ReleaseYear: Int32Ptr(2006),
|
||||
LanguageID: 1,
|
||||
RentalRate: 4.99,
|
||||
Length: int16Ptr(48),
|
||||
Length: Int16Ptr(48),
|
||||
ReplacementCost: 12.99,
|
||||
Rating: &gRating,
|
||||
RentalDuration: 3,
|
||||
LastUpdate: *timestampWithoutTimeZone("2013-05-26 14:50:58.951", 3),
|
||||
SpecialFeatures: stringPtr("{Trailers,\"Deleted Scenes\"}"),
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2013-05-26 14:50:58.951", 3),
|
||||
SpecialFeatures: StringPtr("{Trailers,\"Deleted Scenes\"}"),
|
||||
Fulltext: "'ace':1 'administr':9 'ancient':19 'astound':4 'car':17 'china':20 'databas':8 'epistl':5 'explor':12 'find':15 'goldfing':2 'must':14",
|
||||
})
|
||||
}
|
||||
|
|
@ -1018,7 +1019,7 @@ ORDER BY SUM(payment.amount) ASC;
|
|||
SUMf(Payment.Amount).GT(Float(100)),
|
||||
)
|
||||
|
||||
assertStatementSql(t, customersPaymentQuery, expectedSQL, float64(100))
|
||||
testutils.AssertStatementSql(t, customersPaymentQuery, expectedSQL, float64(100))
|
||||
|
||||
type CustomerPaymentSum struct {
|
||||
CustomerID int16
|
||||
|
|
@ -1088,7 +1089,7 @@ ORDER BY customer_payment_sum."amount_sum" ASC;
|
|||
).
|
||||
ORDER_BY(amountSum.ASC())
|
||||
|
||||
assertStatementSql(t, query, expectedSQL)
|
||||
testutils.AssertStatementSql(t, query, expectedSQL)
|
||||
|
||||
type CustomerWithAmounts struct {
|
||||
Customer *model.Customer
|
||||
|
|
@ -1106,11 +1107,11 @@ ORDER BY customer_payment_sum."amount_sum" ASC;
|
|||
FirstName: "Brian",
|
||||
LastName: "Wyman",
|
||||
AddressID: 323,
|
||||
Email: stringPtr("brian.wyman@sakilacustomer.org"),
|
||||
Email: StringPtr("brian.wyman@sakilacustomer.org"),
|
||||
Activebool: true,
|
||||
CreateDate: *timestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: timestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: int32Ptr(1),
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: Int32Ptr(1),
|
||||
})
|
||||
|
||||
assert.Equal(t, customersWithAmounts[0].AmountSum, 27.93)
|
||||
|
|
@ -1123,7 +1124,7 @@ func TestSelectStaff(t *testing.T) {
|
|||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assertJSON(t, staffs, `
|
||||
testutils.AssertJSON(t, staffs, `
|
||||
[
|
||||
{
|
||||
"StaffID": 1,
|
||||
|
|
@ -1173,7 +1174,7 @@ ORDER BY payment.payment_date ASC;
|
|||
WHERE(Payment.PaymentDate.LT(Timestamp(2007, 02, 14, 22, 16, 01, 0))).
|
||||
ORDER_BY(Payment.PaymentDate.ASC())
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, "2007-02-14 22:16:01.000")
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, "2007-02-14 22:16:01.000")
|
||||
|
||||
payments := []model.Payment{}
|
||||
|
||||
|
|
@ -1190,7 +1191,7 @@ ORDER BY payment.payment_date ASC;
|
|||
StaffID: 2,
|
||||
RentalID: 1158,
|
||||
Amount: 2.99,
|
||||
PaymentDate: *timestampWithoutTimeZone("2007-02-14 21:21:59.996577", 6),
|
||||
PaymentDate: *testutils.TimestampWithoutTimeZone("2007-02-14 21:21:59.996577", 6),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1227,7 +1228,7 @@ OFFSET 20;
|
|||
LIMIT(10).
|
||||
OFFSET(20)
|
||||
|
||||
assertStatementSql(t, query, expectedQuery, float64(100), float64(200), int64(10), int64(20))
|
||||
testutils.AssertStatementSql(t, query, expectedQuery, float64(100), float64(200), int64(10), int64(20))
|
||||
|
||||
dest := []model.Payment{}
|
||||
|
||||
|
|
@ -1301,7 +1302,7 @@ LIMIT 20;
|
|||
ORDER_BY(Payment.PaymentID.ASC()).
|
||||
LIMIT(20)
|
||||
|
||||
assertStatementSql(t, query, expectedQuery, int64(1), "ONE", int64(2), "TWO", int64(3), "THREE", "OTHER", int64(20))
|
||||
testutils.AssertStatementSql(t, query, expectedQuery, int64(1), "ONE", int64(2), "TWO", int64(3), "THREE", "OTHER", int64(20))
|
||||
|
||||
dest := []struct {
|
||||
StaffIDNum string
|
||||
|
|
@ -1337,7 +1338,7 @@ FOR`
|
|||
for lockType, lockTypeStr := range getRowLockTestData() {
|
||||
query.FOR(lockType)
|
||||
|
||||
assertStatementSql(t, query, expectedSQL+" "+lockTypeStr+";\n", int64(3))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL+" "+lockTypeStr+";\n", int64(3))
|
||||
|
||||
tx, _ := db.Begin()
|
||||
|
||||
|
|
@ -1353,7 +1354,7 @@ FOR`
|
|||
for lockType, lockTypeStr := range getRowLockTestData() {
|
||||
query.FOR(lockType.NOWAIT())
|
||||
|
||||
assertStatementSql(t, query, expectedSQL+" "+lockTypeStr+" NOWAIT;\n", int64(3))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL+" "+lockTypeStr+" NOWAIT;\n", int64(3))
|
||||
|
||||
tx, _ := db.Begin()
|
||||
|
||||
|
|
@ -1369,7 +1370,7 @@ FOR`
|
|||
for lockType, lockTypeStr := range getRowLockTestData() {
|
||||
query.FOR(lockType.SKIP_LOCKED())
|
||||
|
||||
assertStatementSql(t, query, expectedSQL+" "+lockTypeStr+" SKIP LOCKED;\n", int64(3))
|
||||
testutils.AssertStatementSql(t, query, expectedSQL+" "+lockTypeStr+" SKIP LOCKED;\n", int64(3))
|
||||
|
||||
tx, _ := db.Begin()
|
||||
|
||||
|
|
@ -1440,7 +1441,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
|
|||
Film.FilmID.ASC(),
|
||||
)
|
||||
|
||||
assertStatementSql(t, stmt, expectedSQL, "English", "Action", int64(180))
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL, "English", "Action", int64(180))
|
||||
|
||||
var dest []struct {
|
||||
model.Actor
|
||||
|
|
@ -1458,7 +1459,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/quick-start-dest.json", dest)
|
||||
assertJSONFile(t, "./testdata/quick-start-dest.json", dest)
|
||||
testutils.AssertJSONFile(t, "./testdata/quick-start-dest.json", dest)
|
||||
|
||||
var dest2 []struct {
|
||||
model.Category
|
||||
|
|
@ -1471,7 +1472,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/quick-start-dest2.json", dest2)
|
||||
assertJSONFile(t, "./testdata/quick-start-dest2.json", dest2)
|
||||
testutils.AssertJSONFile(t, "./testdata/quick-start-dest2.json", dest2)
|
||||
}
|
||||
|
||||
func TestQuickStartWithSubQueries(t *testing.T) {
|
||||
|
|
@ -1523,7 +1524,7 @@ func TestQuickStartWithSubQueries(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/quick-start-dest.json", dest)
|
||||
assertJSONFile(t, "./testdata/quick-start-dest.json", dest)
|
||||
testutils.AssertJSONFile(t, "./testdata/quick-start-dest.json", dest)
|
||||
|
||||
var dest2 []struct {
|
||||
model.Category
|
||||
|
|
@ -1536,5 +1537,5 @@ func TestQuickStartWithSubQueries(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/quick-start-dest2.json", dest2)
|
||||
assertJSONFile(t, "./testdata/quick-start-dest2.json", dest2)
|
||||
testutils.AssertJSONFile(t, "./testdata/quick-start-dest2.json", dest2)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package tests
|
|||
import (
|
||||
"context"
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"gotest.tools/assert"
|
||||
|
|
@ -23,7 +24,7 @@ UPDATE test_sample.link
|
|||
SET (name, url) = ('Bong', 'http://bong.com')
|
||||
WHERE link.name = 'Bing';
|
||||
`
|
||||
assertStatementSql(t, query, expectedSQL, "Bong", "http://bong.com", "Bing")
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, "Bong", "http://bong.com", "Bing")
|
||||
|
||||
assertExec(t, query, 1)
|
||||
|
||||
|
|
@ -68,7 +69,7 @@ SET (name, url) = ((
|
|||
WHERE link.name = 'Bing';
|
||||
`
|
||||
|
||||
assertStatementSql(t, query, expectedSQL, "Bong", "Bing", "Bing")
|
||||
testutils.AssertStatementSql(t, query, expectedSQL, "Bong", "Bing", "Bing")
|
||||
|
||||
assertExec(t, query, 1)
|
||||
}
|
||||
|
|
@ -92,7 +93,7 @@ RETURNING link.id AS "link.id",
|
|||
WHERE(Link.Name.EQ(String("Ask"))).
|
||||
RETURNING(Link.AllColumns)
|
||||
|
||||
assertStatementSql(t, stmt, expectedSQL, "DuckDuckGo", "http://www.duckduckgo.com", "Ask")
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL, "DuckDuckGo", "http://www.duckduckgo.com", "Ask")
|
||||
|
||||
links := []model.Link{}
|
||||
|
||||
|
|
@ -126,7 +127,7 @@ SET (id, url, name, description) = (
|
|||
)
|
||||
WHERE link.id = 0;
|
||||
`
|
||||
assertStatementSql(t, stmt, expectedSQL, int64(0), int64(0))
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL, int64(0), int64(0))
|
||||
|
||||
assertExec(t, stmt, 1)
|
||||
}
|
||||
|
|
@ -151,7 +152,7 @@ SET (id, url, name, description) = (
|
|||
)
|
||||
WHERE link.id = 0;
|
||||
`
|
||||
assertStatementSql(t, stmt, expectedSQL, int64(0), int64(0))
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL, int64(0), int64(0))
|
||||
|
||||
assertExecErr(t, stmt, "pq: number of columns does not match number of values")
|
||||
}
|
||||
|
|
@ -175,7 +176,7 @@ UPDATE test_sample.link
|
|||
SET (id, url, name, description) = (201, 'http://www.duckduckgo.com', 'DuckDuckGo', NULL)
|
||||
WHERE link.id = 201;
|
||||
`
|
||||
assertStatementSql(t, stmt, expectedSQL, int32(201), "http://www.duckduckgo.com", "DuckDuckGo", nil, int64(201))
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL, int32(201), "http://www.duckduckgo.com", "DuckDuckGo", nil, int64(201))
|
||||
|
||||
assertExec(t, stmt, 1)
|
||||
}
|
||||
|
|
@ -202,7 +203,7 @@ UPDATE test_sample.link
|
|||
SET (description, name, url) = (NULL, 'DuckDuckGo', 'http://www.duckduckgo.com')
|
||||
WHERE link.id = 201;
|
||||
`
|
||||
assertStatementSql(t, stmt, expectedSQL, nil, "DuckDuckGo", "http://www.duckduckgo.com", int64(201))
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL, nil, "DuckDuckGo", "http://www.duckduckgo.com", int64(201))
|
||||
|
||||
assertExec(t, stmt, 1)
|
||||
}
|
||||
|
|
@ -238,7 +239,7 @@ UPDATE test_sample.link
|
|||
SET (id, url, name, description, rel) = ('http://www.duckduckgo.com', 'DuckDuckGo', NULL, NULL)
|
||||
WHERE link.id = 201;
|
||||
`
|
||||
assertStatementSql(t, stmt, expectedSQL, "http://www.duckduckgo.com", "DuckDuckGo", nil, nil, int64(201))
|
||||
testutils.AssertStatementSql(t, stmt, expectedSQL, "http://www.duckduckgo.com", "DuckDuckGo", nil, nil, int64(201))
|
||||
|
||||
assertExecErr(t, stmt, "pq: number of columns does not match number of values")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package tests
|
|||
|
||||
import (
|
||||
"github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model"
|
||||
"github.com/google/uuid"
|
||||
"gotest.tools/assert"
|
||||
|
|
@ -10,18 +11,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func assertStatementSql(t *testing.T, query jet.Statement, expectedQuery string, expectedArgs ...interface{}) {
|
||||
_, args, err := query.Sql()
|
||||
assert.NilError(t, err)
|
||||
//assert.Equal(t, queryStr, expectedQuery)
|
||||
assert.DeepEqual(t, args, expectedArgs)
|
||||
|
||||
debuqSql, err := query.DebugSql()
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, debuqSql, expectedQuery)
|
||||
}
|
||||
|
||||
func assertExec(t *testing.T, stmt jet.Statement, rowsAffected int64) {
|
||||
res, err := stmt.Exec(db)
|
||||
|
||||
|
|
@ -36,44 +25,44 @@ func assertExecErr(t *testing.T, stmt jet.Statement, errorStr string) {
|
|||
|
||||
assert.Error(t, err, errorStr)
|
||||
}
|
||||
func boolPtr(b bool) *bool {
|
||||
func BoolPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
func int16Ptr(i int16) *int16 {
|
||||
func Int16Ptr(i int16) *int16 {
|
||||
return &i
|
||||
}
|
||||
|
||||
func int32Ptr(i int32) *int32 {
|
||||
func Int32Ptr(i int32) *int32 {
|
||||
return &i
|
||||
}
|
||||
|
||||
func int64Ptr(i int64) *int64 {
|
||||
func Int64Ptr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
func stringPtr(s string) *string {
|
||||
func StringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
func byteArrayPtr(arr []byte) *[]byte {
|
||||
func ByteArrayPtr(arr []byte) *[]byte {
|
||||
return &arr
|
||||
}
|
||||
|
||||
func float32Ptr(f float32) *float32 {
|
||||
func Float32Ptr(f float32) *float32 {
|
||||
return &f
|
||||
}
|
||||
func float64Ptr(f float64) *float64 {
|
||||
func Float64Ptr(f float64) *float64 {
|
||||
return &f
|
||||
}
|
||||
|
||||
func uuidPtr(u string) *uuid.UUID {
|
||||
func UUIDPtr(u string) *uuid.UUID {
|
||||
newUUID := uuid.MustParse(u)
|
||||
|
||||
return &newUUID
|
||||
}
|
||||
|
||||
func timeWithoutTimeZone(t string) *time.Time {
|
||||
func TimeWithoutTimeZone(t string) *time.Time {
|
||||
newTime, err := time.Parse("15:04:05", t)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -83,7 +72,7 @@ func timeWithoutTimeZone(t string) *time.Time {
|
|||
return &newTime
|
||||
}
|
||||
|
||||
func timeWithTimeZone(t string) *time.Time {
|
||||
func TimeWithTimeZone(t string) *time.Time {
|
||||
newTimez, err := time.Parse("15:04:05 -0700", t)
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -93,24 +82,7 @@ func timeWithTimeZone(t string) *time.Time {
|
|||
return &newTimez
|
||||
}
|
||||
|
||||
func timestampWithoutTimeZone(t string, precision int) *time.Time {
|
||||
|
||||
precisionStr := ""
|
||||
|
||||
if precision > 0 {
|
||||
precisionStr = "." + strings.Repeat("9", precision)
|
||||
}
|
||||
|
||||
newTime, err := time.Parse("2006-01-02 15:04:05"+precisionStr+" +0000", t+" +0000")
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &newTime
|
||||
}
|
||||
|
||||
func timestampWithTimeZone(t string, precision int) *time.Time {
|
||||
func TimestampWithTimeZone(t string, precision int) *time.Time {
|
||||
|
||||
precisionStr := ""
|
||||
|
||||
|
|
@ -132,12 +104,12 @@ var customer0 = model.Customer{
|
|||
StoreID: 1,
|
||||
FirstName: "Mary",
|
||||
LastName: "Smith",
|
||||
Email: stringPtr("mary.smith@sakilacustomer.org"),
|
||||
Email: StringPtr("mary.smith@sakilacustomer.org"),
|
||||
AddressID: 5,
|
||||
Activebool: true,
|
||||
CreateDate: *timestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: timestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: int32Ptr(1),
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
|
||||
var customer1 = model.Customer{
|
||||
|
|
@ -145,12 +117,12 @@ var customer1 = model.Customer{
|
|||
StoreID: 1,
|
||||
FirstName: "Patricia",
|
||||
LastName: "Johnson",
|
||||
Email: stringPtr("patricia.johnson@sakilacustomer.org"),
|
||||
Email: StringPtr("patricia.johnson@sakilacustomer.org"),
|
||||
AddressID: 6,
|
||||
Activebool: true,
|
||||
CreateDate: *timestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: timestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: int32Ptr(1),
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
|
||||
var lastCustomer = model.Customer{
|
||||
|
|
@ -158,10 +130,10 @@ var lastCustomer = model.Customer{
|
|||
StoreID: 2,
|
||||
FirstName: "Austin",
|
||||
LastName: "Cintron",
|
||||
Email: stringPtr("austin.cintron@sakilacustomer.org"),
|
||||
Email: StringPtr("austin.cintron@sakilacustomer.org"),
|
||||
AddressID: 605,
|
||||
Activebool: true,
|
||||
CreateDate: *timestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: timestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: int32Ptr(1),
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue