2019-06-21 13:56:57 +02:00
|
|
|
package jet
|
2019-04-14 17:55:10 +02:00
|
|
|
|
2019-04-20 19:49:29 +02:00
|
|
|
import (
|
2019-04-29 14:39:48 +02:00
|
|
|
"errors"
|
2019-07-04 17:54:15 +02:00
|
|
|
"github.com/go-jet/jet/internal/utils"
|
2019-06-05 17:15:20 +02:00
|
|
|
"reflect"
|
2019-06-30 11:53:35 +02:00
|
|
|
"strings"
|
2019-04-20 19:49:29 +02:00
|
|
|
)
|
2019-04-14 17:55:10 +02:00
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
func serializeOrderByClauseList(statement StatementType, orderByClauses []OrderByClause, out *SqlBuilder) error {
|
2019-04-29 14:39:48 +02:00
|
|
|
|
|
|
|
|
for i, value := range orderByClauses {
|
2019-04-14 17:55:10 +02:00
|
|
|
if i > 0 {
|
2019-08-03 14:10:47 +02:00
|
|
|
out.WriteString(", ")
|
2019-04-14 17:55:10 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-11 12:47:35 +02:00
|
|
|
err := value.serializeForOrderBy(statement, out)
|
2019-04-14 17:55:10 +02:00
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
func serializeGroupByClauseList(statement StatementType, clauses []GroupByClause, out *SqlBuilder) (err error) {
|
2019-04-29 14:39:48 +02:00
|
|
|
|
|
|
|
|
for i, c := range clauses {
|
2019-04-14 17:55:10 +02:00
|
|
|
if i > 0 {
|
2019-08-03 14:10:47 +02:00
|
|
|
out.WriteString(", ")
|
2019-04-29 14:39:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == nil {
|
2019-07-18 17:43:11 +02:00
|
|
|
return errors.New("jet: nil clause")
|
2019-04-14 17:55:10 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-08 13:47:01 +02:00
|
|
|
if err = c.serializeForGroupBy(statement, out); err != nil {
|
2019-04-29 14:39:48 +02:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
func SerializeClauseList(statement StatementType, clauses []Serializer, out *SqlBuilder) (err error) {
|
2019-05-07 19:06:21 +02:00
|
|
|
|
|
|
|
|
for i, c := range clauses {
|
|
|
|
|
if i > 0 {
|
2019-08-03 14:10:47 +02:00
|
|
|
out.WriteString(", ")
|
2019-05-07 19:06:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == nil {
|
2019-07-18 17:43:11 +02:00
|
|
|
return errors.New("jet: nil clause")
|
2019-05-07 19:06:21 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-08 13:47:01 +02:00
|
|
|
if err = c.serialize(statement, out); err != nil {
|
2019-05-07 19:06:21 +02:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-03 14:10:47 +02:00
|
|
|
func serializeExpressionList(statement StatementType, expressions []Expression, separator string, out *SqlBuilder) error {
|
2019-04-29 14:39:48 +02:00
|
|
|
|
|
|
|
|
for i, value := range expressions {
|
|
|
|
|
if i > 0 {
|
2019-08-03 14:10:47 +02:00
|
|
|
out.WriteString(separator)
|
2019-04-29 14:39:48 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-08 13:47:01 +02:00
|
|
|
err := value.serialize(statement, out)
|
2019-04-14 17:55:10 +02:00
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2019-04-20 19:49:29 +02:00
|
|
|
|
2019-08-03 14:10:47 +02:00
|
|
|
func SerializeProjectionList(statement StatementType, projections []Projection, out *SqlBuilder) error {
|
2019-04-29 14:39:48 +02:00
|
|
|
for i, col := range projections {
|
|
|
|
|
if i > 0 {
|
2019-08-03 14:10:47 +02:00
|
|
|
out.WriteString(",")
|
2019-08-11 12:13:59 +02:00
|
|
|
out.NewLine()
|
2019-04-29 14:39:48 +02:00
|
|
|
}
|
2019-05-12 18:15:23 +02:00
|
|
|
|
2019-04-29 14:39:48 +02:00
|
|
|
if col == nil {
|
2019-08-03 14:10:47 +02:00
|
|
|
return errors.New("jet: Projection is nil")
|
2019-04-29 14:39:48 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-08 13:47:01 +02:00
|
|
|
if err := col.serializeForProjection(statement, out); err != nil {
|
2019-04-29 14:39:48 +02:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-03 14:10:47 +02:00
|
|
|
func SerializeColumnNames(columns []IColumn, out *SqlBuilder) error {
|
2019-04-29 14:39:48 +02:00
|
|
|
for i, col := range columns {
|
|
|
|
|
if i > 0 {
|
2019-08-03 14:10:47 +02:00
|
|
|
out.WriteString(", ")
|
2019-04-29 14:39:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if col == nil {
|
2019-07-08 13:00:44 +02:00
|
|
|
return errors.New("jet: nil column in columns list")
|
2019-04-29 14:39:48 +02:00
|
|
|
}
|
|
|
|
|
|
2019-08-03 14:10:47 +02:00
|
|
|
out.WriteString(col.Name())
|
2019-04-29 14:39:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-03 14:10:47 +02:00
|
|
|
func ColumnListToProjectionList(columns []Column) []Projection {
|
|
|
|
|
var ret []Projection
|
2019-06-15 13:58:45 +02:00
|
|
|
|
|
|
|
|
for _, column := range columns {
|
|
|
|
|
ret = append(ret, column)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
func valueToClause(value interface{}) Serializer {
|
|
|
|
|
if clause, ok := value.(Serializer); ok {
|
2019-06-14 14:35:50 +02:00
|
|
|
return clause
|
|
|
|
|
}
|
2019-07-18 17:43:11 +02:00
|
|
|
|
|
|
|
|
return literal(value)
|
2019-06-14 14:35:50 +02:00
|
|
|
}
|
|
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
func UnwindRowFromModel(columns []IColumn, data interface{}) []Serializer {
|
2019-06-14 14:35:50 +02:00
|
|
|
structValue := reflect.Indirect(reflect.ValueOf(data))
|
|
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
row := []Serializer{}
|
2019-06-14 14:35:50 +02:00
|
|
|
|
2019-06-15 13:58:45 +02:00
|
|
|
mustBe(structValue, reflect.Struct)
|
2019-06-14 14:35:50 +02:00
|
|
|
|
|
|
|
|
for _, column := range columns {
|
|
|
|
|
columnName := column.Name()
|
2019-07-04 17:54:15 +02:00
|
|
|
structFieldName := utils.ToGoIdentifier(columnName)
|
2019-06-14 14:35:50 +02:00
|
|
|
|
|
|
|
|
structField := structValue.FieldByName(structFieldName)
|
|
|
|
|
|
|
|
|
|
if !structField.IsValid() {
|
2019-06-15 13:58:45 +02:00
|
|
|
panic("missing struct field for column : " + column.Name())
|
2019-06-14 14:35:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var field interface{}
|
|
|
|
|
|
|
|
|
|
if structField.Kind() == reflect.Ptr && structField.IsNil() {
|
|
|
|
|
field = nil
|
|
|
|
|
} else {
|
|
|
|
|
field = reflect.Indirect(structField).Interface()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
row = append(row, literal(field))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return row
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
func UnwindRowsFromModels(columns []IColumn, data interface{}) [][]Serializer {
|
2019-06-30 11:53:35 +02:00
|
|
|
sliceValue := reflect.Indirect(reflect.ValueOf(data))
|
|
|
|
|
mustBe(sliceValue, reflect.Slice)
|
|
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
rows := [][]Serializer{}
|
2019-06-30 11:53:35 +02:00
|
|
|
|
|
|
|
|
for i := 0; i < sliceValue.Len(); i++ {
|
|
|
|
|
structValue := sliceValue.Index(i)
|
|
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
rows = append(rows, UnwindRowFromModel(columns, structValue.Interface()))
|
2019-06-30 11:53:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rows
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-11 09:52:02 +02:00
|
|
|
func UnwindRowFromValues(value interface{}, values []interface{}) []Serializer {
|
|
|
|
|
row := []Serializer{}
|
2019-06-14 14:35:50 +02:00
|
|
|
|
|
|
|
|
allValues := append([]interface{}{value}, values...)
|
|
|
|
|
|
|
|
|
|
for _, val := range allValues {
|
|
|
|
|
row = append(row, valueToClause(val))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return row
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-30 11:53:35 +02:00
|
|
|
func mustBe(v reflect.Value, expectedKinds ...reflect.Kind) {
|
|
|
|
|
indirectV := reflect.Indirect(v)
|
|
|
|
|
types := []string{}
|
|
|
|
|
|
|
|
|
|
for _, expectedKind := range expectedKinds {
|
|
|
|
|
types = append(types, expectedKind.String())
|
|
|
|
|
if k := indirectV.Kind(); k == expectedKind {
|
|
|
|
|
return
|
|
|
|
|
}
|
2019-06-09 11:06:08 +02:00
|
|
|
}
|
2019-06-30 11:53:35 +02:00
|
|
|
|
|
|
|
|
panic("argument mismatch: expected " + strings.Join(types, " or ") + ", got " + v.Type().String())
|
2019-06-09 11:06:08 +02:00
|
|
|
}
|