Kepler core
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

718 lines
26 KiB

package restlet
import (
"encoding/json"
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/archsh/go.xql"
_ "github.com/archsh/go.xql/dialects/postgres"
"reflect"
"strconv"
"strings"
"time"
)
type CURDKind interface {
Entity() xql.TableIdentified
}
type CURDTable interface {
Table() *xql.Table
}
type CURDPreRead interface {
PreRead(ctx RequestContext, session *xql.Session, url_params Parameters, queries Parameters) (*QueryController, error)
}
type CURDPreCreate interface {
PreCreate(ctx RequestContext, session *xql.Session, url_params Parameters, queries Parameters, entity interface{}) error
}
type CURDPreUpdate interface {
PreUpdate(ctx RequestContext, session *xql.Session, url_params Parameters, queries Parameters, columns []xql.UpdateColumn) (*QueryController, []xql.UpdateColumn, error)
}
type CURDPreDelete interface {
PreDelete(ctx RequestContext, session *xql.Session, url_params Parameters, queries Parameters) (*QueryController, error)
}
type CURDPostRead interface {
PostRead(ctx RequestContext, session *xql.Session, qc *QueryController, entity interface{}) (interface{}, error)
}
type CURDPostCreate interface {
PostCreate(ctx RequestContext, session *xql.Session, entity interface{}) (interface{}, error)
}
type CURDPostUpdate interface {
PostUpdate(ctx RequestContext, session *xql.Session, qc *QueryController, columns []xql.UpdateColumn) ([]xql.UpdateColumn, error)
}
type CURDPostDelete interface {
PostDelete(ctx RequestContext, session *xql.Session, qc *QueryController) error
}
type CURDOnRead interface {
OnRead(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error)
}
type CURDOnCreate interface {
OnCreate(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error)
}
type CURDOnUpdate interface {
OnUpdate(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error)
}
type CURDOnDelete interface {
OnDelete(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error)
}
type DefaultCURDHandler struct {
dbiName string
table *xql.Table
entity xql.TableIdentified
pks []string
notAllowed []string
query QueryMaker
preRead CURDPreRead
preCreate CURDPreCreate
preUpdate CURDPreUpdate
preDelete CURDPreDelete
postRead CURDPostRead
postCreate CURDPostCreate
postUpdate CURDPostUpdate
postDelete CURDPostDelete
onRead CURDOnRead
onCreate CURDOnCreate
onUpdate CURDOnUpdate
onDelete CURDOnDelete
}
func (h DefaultCURDHandler) Handle(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error) {
for _, x := range h.notAllowed {
if strings.ToUpper(x) == ctx.Request().Method {
return Failure_Response(ERROR_METHOD_NOT_ALLOWED, "Method Not Allowed!")
}
}
switch ctx.Request().Method {
case "GET":
if h.onRead != nil {
return h.onRead.OnRead(ctx, url_params, queries, post_data)
}
return h.read(ctx, url_params, queries, post_data)
case "PATCH":
if h.onUpdate != nil {
return h.onUpdate.OnUpdate(ctx, url_params, queries, post_data)
}
return h.update(ctx, url_params, queries, post_data)
case "PUT":
if h.onUpdate != nil {
return h.onUpdate.OnUpdate(ctx, url_params, queries, post_data)
}
return h.update(ctx, url_params, queries, post_data)
case "POST":
if h.onCreate != nil {
return h.onCreate.OnCreate(ctx, url_params, queries, post_data)
}
return h.create(ctx, url_params, queries, post_data)
case "DELETE":
if h.onDelete != nil {
return h.onDelete.OnDelete(ctx, url_params, queries, post_data)
}
return h.delete(ctx, url_params, queries, post_data)
case "OPTIONS":
return h.options(ctx, url_params, queries, post_data)
default:
return Failure_Response(ERROR_METHOD_NOT_ALLOWED, "Method Not Allowed!")
}
}
func (h DefaultCURDHandler) options(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error) {
result := &RestletResult{}
result.Model = reflect.TypeOf(h.entity).Name()
result.Data = h.entity
return result, nil
}
func (h DefaultCURDHandler) read(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error) {
session := xql.MakeSession(ctx.SQL(h.dbiName), "postgres")
defer session.Close()
result := &RestletResult{}
entityType := reflect.TypeOf(h.entity)
if val := reflect.ValueOf(h.entity); val.Kind() == reflect.Ptr {
entityType = val.Elem().Type() //reflect.TypeOf()
}
log.Debugln("DefaultCURDHandler.read> ", h.table.TableName, entityType)
var queryControl *QueryController
if h.preRead != nil {
qc, e := h.preRead.PreRead(ctx, session, url_params, queries)
if nil != e {
return Failure_Response(ERROR_BAD_REQUEST, fmt.Sprintf("%s", e))
}
queryControl = qc
} else if qc, err := Build_QueryControl(queries, h.table, h.query); nil != err {
log.Errorln("DefaultCURDHandler.read:> failure:", err)
return Failure_Response(ERROR_BAD_REQUEST, fmt.Sprintf("%s", err))
} else {
queryControl = qc
}
var pk_mapping = _build_params_map(h.table, url_params, h.pks...)
if nil != pk_mapping && len(pk_mapping)==len(h.pks) {
obj := reflect.New(entityType)
row := session.Query(h.table, queryControl.Includes...).Filter(pk_mapping).One()
err := row.Scan(obj.Elem().Addr().Interface())
if nil != err {
log.Errorln("DefaultCURDHandler.read:2> failure:", reflect.TypeOf(err), err)
return Failure_Response(ERROR_NOT_FOUND, "Record Not Found!")
}
result.Data = obj.Elem().Addr().Interface()
} else {
for k, v := range url_params {
f := xql.QueryFilter{Field: k, Operator: "="}
f.Value = _build_column_query_value(h.table, k, f.Operator, v)
queryControl.Filters = append(queryControl.Filters, f)
}
qs := session.Query(h.table, queryControl.Includes...).Filter(queryControl.Filters...)
total, err := qs.Count()
if nil != err {
log.Errorln("DefaultCURDHandler.read:> failure:", err)
return Failure_Response(FATAL_DB_READ_FAILED, fmt.Sprintf("%s", err))
}
result.Control = &ControlResult{}
result.Control.Total = total
result.Control.Offset = queryControl.Offset
result.Control.Limit = queryControl.Limit
qs = qs.Offset(queryControl.Offset).Limit(queryControl.Limit)
qs = qs.OrderBy(queryControl.OrderBy...)
rows, err := qs.All()
if nil != err {
log.Errorln("DefaultCURDHandler.read:> failure:", err)
return Failure_Response(FATAL_DB_READ_FAILED, fmt.Sprintf("%s", err))
}
defer rows.Close()
objects := reflect.MakeSlice(reflect.SliceOf(reflect.PtrTo(entityType)), 0, 0)
for rows.Next() {
obj := reflect.New(entityType)
err = rows.Scan(obj.Elem().Addr().Interface())
if nil != err {
log.Errorln("DefaultCURDHandler.read:> failure:", err)
return Failure_Response(FATAL_DB_READ_FAILED, fmt.Sprintf("%s", err))
}
objects = reflect.Append(objects, obj)
result.Control.Count += 1
}
result.Model = reflect.TypeOf(h.entity).Name()
result.Data = objects.Interface()
}
if h.postRead != nil {
if ret, e := h.postRead.PostRead(ctx, session, queryControl, result.Data); nil != e {
log.Errorln("DefaultCURDHandler.read:> failure:", e)
return Failure_Response(FATAL_DB_READ_FAILED, fmt.Sprintf("%s", e))
} else {
result.Data = ret
}
}
return result, nil
}
func (h DefaultCURDHandler) create(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error) {
entityType := reflect.TypeOf(h.entity)
if val := reflect.ValueOf(h.entity); val.Kind() == reflect.Ptr {
entityType = val.Elem().Type() //reflect.TypeOf()
}
log.Debugln("DefaultCURDHandler.create> ", h.table.TableName, entityType)
if nil == post_data || len(post_data) < 1 {
return Failure_Response(ERROR_INVALID_DATA, "Empty Data!")
}
session := xql.MakeSession(ctx.SQL(h.dbiName), "postgres")
defer session.Close()
entityObjs := reflect.MakeSlice(reflect.SliceOf(entityType), 1, 2)
p := reflect.New(reflect.SliceOf(entityType))
reflect.Indirect(p).Set(entityObjs)
if err := json.Unmarshal(post_data, entityObjs.Index(0).Addr().Interface()); nil == err {
log.Debugln("DefaultCURDHandler.create>>>: Single Object")
} else if err = json.Unmarshal(post_data, p.Interface()); nil == err {
log.Debugln("DefaultCURDHandler.create>>>: Slice Objects")
} else {
log.Warnln("DefaultCURDHandler.create> Invalid Data:", err)
return Failure_Response(ERROR_INVALID_DATA, "Invalid Data!")
}
var pk_mapping = _build_params_map(h.table, url_params, h.pks...)
for k, v := range url_params {
if nil == pk_mapping {
pk_mapping = make(map[string]interface{})
pk_mapping[k] = _build_column_query_value(h.table, k, "=", v)
continue
}
if _, ok := pk_mapping[k]; ! ok {
pk_mapping[k] = _build_column_query_value(h.table, k, "=", v)
}
}
result := &RestletResult{}
err := session.Begin()
if nil != err {
log.Errorln("DefaultCURDHandler.create:> failure:", err)
return Failure_Response(FATAL_DB_WRITE_FAILED, fmt.Sprintf("%s", err))
}
//n := 0
for i := 0; i < entityObjs.Len(); i++ {
obj := entityObjs.Index(i)
if nil != pk_mapping {
_assign_entity_from_map(obj.Addr().Interface(), pk_mapping, false)
}
if h.preCreate != nil {
if e := h.preCreate.PreCreate(ctx, session, url_params, queries, obj.Addr().Interface()); nil != e {
log.Errorln("DefaultCURDHandler.create> preCreate failed:", e)
return Failure_Response(ERROR_INVALID_DATA, fmt.Sprintf("%s", e))
}
}
log.Debugln("DefaultCURDHandler.create:> Inserting :", obj.Addr().Interface())
_, err = session.Query(h.table).Insert(obj.Addr().Interface())
if nil != err {
log.Errorln("DefaultCURDHandler.create:> failure:", err)
session.Rollback()
return Failure_Response(FATAL_DB_WRITE_FAILED, fmt.Sprintf("%s", err))
}
}
result.Data = entityObjs.Interface()
if h.postCreate != nil {
if ret, e := h.postCreate.PostCreate(ctx, session, result.Data); nil != e {
log.Errorln("DefaultCURDHandler.create:> postCreate failed:", e)
return Failure_Response(FATAL_DB_WRITE_FAILED, fmt.Sprintf("%s", e))
} else {
result.Data = ret
}
}
err = session.Commit()
if nil != err {
log.Errorln("DefaultCURDHandler.create:> failure:", err)
session.Rollback()
return Failure_Response(FATAL_DB_WRITE_FAILED, fmt.Sprintf("%s", err))
}
result.Code = SUCCESS_CREATED
return result, nil
}
func (h DefaultCURDHandler) update(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error) {
entityType := reflect.TypeOf(h.entity)
if val := reflect.ValueOf(h.entity); val.Kind() == reflect.Ptr {
entityType = val.Elem().Type() //reflect.TypeOf()
}
log.Debugln("DefaultCURDHandler.update> ", h.table.TableName, entityType)
if nil == post_data || len(post_data) < 1 {
log.Warnln("DefaultCURDHandler.update:> Empty DATA.")
return Failure_Response(ERROR_INVALID_DATA, "Empty Data!")
}
entityObj := reflect.New(entityType)
var entityMap = make(map[string]interface{})
err := json.Unmarshal(post_data, entityObj.Elem().Addr().Interface())
e1 := json.Unmarshal(post_data, &entityMap)
if nil != err || nil != e1 {
log.Warnln("DefaultCURDHandler.update:> Invalid DATA:", err, e1)
return Failure_Response(ERROR_INVALID_DATA, "Invalid Data!")
}
for k, _ := range entityMap {
if _, ok := h.table.GetColumn(k); ok {
continue
} else {
log.Warnln("DefaultCURDHandler.update:> Invalid Field:", k)
return Failure_Response(ERROR_INVALID_DATA, "Invalid Field:"+k)
}
}
if len(entityMap) == 0 {
log.Warnln("DefaultCURDHandler.update:> Empty DATA:", err, e1)
return Failure_Response(ERROR_INVALID_DATA, "Empty Data!")
}
session := xql.MakeSession(ctx.SQL(h.dbiName), "postgres")
defer session.Close()
var updateCols []xql.UpdateColumn
for _, c := range h.table.GetColumns() {
if _, ok := entityMap[c.FieldName]; ok {
} else if _, ok := entityMap[c.Jtag]; ok {
} else if _, ok := entityMap[c.ElemName]; ok {
} else {
continue
}
if c.PrimaryKey {
return Failure_Response(ERROR_FORBIDDEN, "Not Allowed to Change Primary Key(s).")
}
uc := xql.UpdateColumn{Field: c.FieldName, Operator: "="}
val := entityObj.Elem().FieldByName(c.ElemName)
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
uc.Value = val.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
uc.Value = val.Uint()
case reflect.String:
uc.Value = val.String()
case reflect.Bool:
uc.Value = val.Bool()
case reflect.Float32, reflect.Float64:
uc.Value = val.Float()
default:
uc.Value = val.Interface()
}
updateCols = append(updateCols, uc)
}
var queryControl *QueryController
if h.preUpdate != nil {
if qc, cols, e := h.preUpdate.PreUpdate(ctx, session, url_params, queries, updateCols); nil != e {
return Failure_Response(ERROR_BAD_REQUEST, fmt.Sprintf("%s", e))
} else {
queryControl = qc
updateCols = cols
}
} else {
if qc, err := Build_QueryControl(queries, h.table, h.query); nil != err {
log.Errorln("DefaultCURDHandler.update:> failure:", err)
return Failure_Response(ERROR_BAD_REQUEST, fmt.Sprintf("%s", err))
} else {
queryControl = qc
}
}
if len(updateCols)<1{
return Failure_Response(ERROR_BAD_REQUEST, "empty update columns...")
}
log.Debugln("DefaultCURDHandler.update> QueryControl:", queryControl)
var pk_mapping = _build_params_map(h.table, url_params, h.pks...)
if nil != pk_mapping {
queryControl.Filters = append(queryControl.Filters, pk_mapping)
}
n, e := session.Query(h.table).Filter(queryControl.Filters...).Update(updateCols)
if nil != e {
log.Errorln("DefaultCURDHandler.update:> failure:", e)
return Failure_Response(FATAL_DB_WRITE_FAILED, fmt.Sprintf("%s", e))
}
if h.postUpdate != nil {
updateCols, e = h.postUpdate.PostUpdate(ctx, session, queryControl, updateCols)
if nil != e {
log.Errorln("DefaultCURDHandler.update:> post update failure:", e)
return Failure_Response(FATAL_DB_WRITE_FAILED, fmt.Sprintf("%s", e))
}
}
var updates = make(map[string]interface{})
for _, x := range updateCols {
updates[x.Field] = x.Value
}
result := &RestletResult{
Code: SUCCESS_OK,
Model: entityType.Name(),
Data: map[string]interface{}{
"count": n,
"updates": updates,
},
}
return result, nil
}
func (h DefaultCURDHandler) delete(ctx RequestContext, url_params Parameters, queries Parameters, post_data []byte) (*RestletResult, error) {
session := xql.MakeSession(ctx.SQL(h.dbiName), "postgres")
defer session.Close()
result := &RestletResult{}
entityType := reflect.TypeOf(h.entity)
if val := reflect.ValueOf(h.entity); val.Kind() == reflect.Ptr {
entityType = val.Elem().Type() //reflect.TypeOf()
}
result.Model = reflect.TypeOf(h.entity).Name()
log.Debugln("DefaultCURDHandler.delete> ", h.table.TableName, entityType)
var queryControl *QueryController
if h.preDelete != nil {
if qc, e := h.preDelete.PreDelete(ctx, session, url_params, queries); nil != e {
log.Errorln("DefaultCURDHandler.delete:> pre delete failure:", e)
return Failure_Response(ERROR_BAD_REQUEST, fmt.Sprintf("%s", e))
} else {
queryControl = qc
}
} else {
if qc, err := Build_QueryControl(queries, h.table, h.query); nil != err {
log.Errorln("DefaultCURDHandler.delete:> failure:", err)
return Failure_Response(ERROR_BAD_REQUEST, fmt.Sprintf("%s", err))
} else {
queryControl = qc
}
}
var pk_mapping = _build_params_map(h.table, url_params, h.pks...)
if nil != pk_mapping {
n, err := session.Query(h.table).Filter(pk_mapping).Delete()
if nil != err {
return Failure_Response(FATAL_DB_WRITE_FAILED, fmt.Sprint(err))
}
result.Code = SUCCESS_DELETED
result.Data = map[string]interface{}{"Deleted": n}
return result, nil
}
for k, v := range url_params {
f := xql.QueryFilter{Field: k, Operator: "="}
f.Value = _build_column_query_value(h.table, k, f.Operator, v)
queryControl.Filters = append(queryControl.Filters, f)
}
if len(queryControl.Filters) < 1 {
return Failure_Response(ERROR_FORBIDDEN, "Not allowed to delete without conditions!")
}
n, err := session.Query(h.table).Filter(queryControl.Filters...).Delete()
if nil != err {
return Failure_Response(FATAL_DB_WRITE_FAILED, fmt.Sprint(err))
}
if h.postDelete != nil {
if e := h.postDelete.PostDelete(ctx, session, queryControl); nil != e {
return Failure_Response(FATAL_DB_WRITE_FAILED, fmt.Sprint(e))
}
}
result.Code = SUCCESS_OK
result.Data = map[string]interface{}{"deleted": n}
return result, nil
}
func NewCURDHandler(dbiname string, kind interface{}, notAllowedMethods ...string) RestletHandler {
var h = DefaultCURDHandler{dbiName: dbiname, notAllowed: notAllowedMethods}
if h.dbiName == "" {
h.dbiName = "default"
}
if k, b := kind.(xql.TableIdentified); b {
h.entity = k
} else if k, b := kind.(CURDKind); b {
h.entity = k.Entity()
} else {
panic("kind param should at least implement CURDKind or xql.TableIdentified interface!")
}
if k, b := kind.(CURDTable); b {
h.table = k.Table()
} else {
h.table = xql.DeclareTable(h.entity)
}
for _, x := range h.table.GetPrimaryKeys() {
h.pks = append(h.pks, x.FieldName)
}
if k, b := kind.(QueryMaker); b {
h.query = k
}
if k, b := kind.(CURDPreRead); b {
h.preRead = k
}
if k, b := kind.(CURDPreCreate); b {
h.preCreate = k
}
if k, b := kind.(CURDPreUpdate); b {
h.preUpdate = k
}
if k, b := kind.(CURDPreDelete); b {
h.preDelete = k
}
if k, b := kind.(CURDPostRead); b {
h.postRead = k
}
if k, b := kind.(CURDPostCreate); b {
h.postCreate = k
}
if k, b := kind.(CURDPostUpdate); b {
h.postUpdate = k
}
if k, b := kind.(CURDPostDelete); b {
h.postDelete = k
}
if k, b := kind.(CURDOnRead); b {
h.onRead = k
}
if k, b := kind.(CURDOnCreate); b {
h.onCreate = k
}
if k, b := kind.(CURDOnUpdate); b {
h.onUpdate = k
}
if k, b := kind.(CURDOnDelete); b {
h.onDelete = k
}
return h
}
func _build_params_map(table *xql.Table, params Parameters, pks ...string) map[string]interface{} {
var pk_mapping map[string]interface{}
for i, pk := range pks {
if v, ok := params.GetString(pk); ok {
//log.Debugln("_build_params_map:> Pk", i, pk, v)
if nil == pk_mapping {
pk_mapping = make(map[string]interface{})
}
pk_mapping[table.GetPrimaryKeys()[i].FieldName] =
_build_column_query_value(table, table.GetPrimaryKeys()[i].FieldName, "=", v)
//delete(params, pk)
}
}
//if len(pks) > 0 {
// return pk_mapping
//}
//for k, v := range params {
// if nil == pk_mapping {
// pk_mapping = make(map[string]interface{})
// }
// pk_mapping[k] = _build_column_query_value(table, k, "=", v)
//}
return pk_mapping
}
func _assign_entity_from_map(entity interface{}, params map[string]interface{}, recursive bool) error {
//log.Debugln("_assign_entity_from_map:>>>", entity, params)
if nil != entity {
et := reflect.TypeOf(entity)
ev := reflect.ValueOf(entity)
for i := 0; i < et.Elem().NumField(); i++ {
f := et.Elem().Field(i)
x_tag := strings.Split(f.Tag.Get("xql"), ",")[0]
if x_tag == "-" {
continue
}
if f.Anonymous && !recursive {
_assign_entity_from_map(ev.Elem().Field(i).Addr().Interface(), params, true)
continue
}
json_tag := strings.Split(f.Tag.Get("json"), ",")[0]
var val interface{}
if v, ok := params[x_tag]; ok {
//log.Debugln("_assign_entity_from_map:>>>", 1, v)
val = v
} else if v, ok := params[json_tag]; ok {
//log.Debugln("_assign_entity_from_map:>>>", 2, v)
val = v
} else if v, ok := params[f.Name]; ok {
//log.Debugln("_assign_entity_from_map:>>>", 3, v)
val = v
} else if v, ok := params[xql.Camel2Underscore(f.Name)]; ok {
//log.Debugln("_assign_entity_from_map:>>>", 4, v)
val = v
} else {
continue
}
fv := ev.Elem().Field(i)
if fv.IsValid() && fv.CanSet() {
fv.Set(reflect.ValueOf(val))
}
}
} else {
panic("Empty pointer of entity!")
}
return nil
}
func translate_datetime(s string) time.Time {
if t, e := time.Parse(time.RFC3339Nano, s); nil == e {
return t
} else if t, e := time.Parse(time.RFC3339, s); nil == e {
return t
} else if t, e := time.Parse("2006-01-02T15:04:05", s); nil == e {
return t
} else if t, e := time.Parse("2006-01-02T15:04", s); nil == e {
return t
} else if t, e := time.Parse("2006-01-02", s); nil == e {
return t
} else if t, e := time.Parse("2006", s); nil == e {
return t
} else {
return time.Time{}
}
}
func translate_single_value(k reflect.Kind, val string) interface{} {
switch k {
case reflect.Bool:
switch strings.ToLower(val) {
case "yes", "true", "y", "t", "ok":
return true
default:
return false
}
case reflect.Int:
n, _ := strconv.ParseInt(val, 10, 32)
return int(n)
case reflect.Int8:
n, _ := strconv.ParseInt(val, 10, 8)
return int8(n)
case reflect.Int16:
n, _ := strconv.ParseInt(val, 10, 16)
return int16(n)
case reflect.Int64:
n, _ := strconv.ParseInt(val, 10, 64)
return int64(n)
case reflect.Uint:
n, _ := strconv.ParseUint(val, 10, 32)
return uint(n)
case reflect.Uint8:
n, _ := strconv.ParseUint(val, 10, 8)
return uint8(n)
case reflect.Uint16:
n, _ := strconv.ParseUint(val, 10, 16)
return uint16(n)
case reflect.Uint64:
n, _ := strconv.ParseUint(val, 10, 64)
return uint64(n)
case reflect.String:
return val
case reflect.Float32:
f, _ := strconv.ParseFloat(val, 32)
return float32(f)
case reflect.Float64:
f, _ := strconv.ParseFloat(val, 64)
return float64(f)
case reflect.TypeOf(time.Time{}).Kind():
t := translate_datetime(val)
return t
case reflect.TypeOf(&time.Time{}).Kind():
t := translate_datetime(val)
return &t
default:
return val
}
return nil
}
func _build_column_query_value(table *xql.Table, field string, operator string, val string) interface{} {
if col, b := table.GetColumn(field); !b {
return val
} else {
if col.Type.Kind() == reflect.Slice {
et := col.Type.Elem()
vv := reflect.MakeSlice(col.Type, 0, 0)
for _, x := range strings.Split(val, ",") {
if x == "" {
continue
}
v := translate_single_value(et.Kind(), x)
//fmt.Println(">>>>", v,reflect.ValueOf(v))
vv = reflect.Append(vv, reflect.ValueOf(v))
//fmt.Println(">>>>",vv)
}
return vv.Interface()
} else if operator == "IN" {
vv := reflect.MakeSlice(reflect.SliceOf(col.Type), 0, 0)
for _, x := range strings.Split(val, ",") {
if x == "" {
continue
}
v := translate_single_value(col.Type.Kind(), x)
//fmt.Println(">>>>", v,reflect.ValueOf(v))
vv = reflect.Append(vv, reflect.ValueOf(v))
//fmt.Println(">>>>",vv)
}
return vv.Interface()
} else {
return translate_single_value(col.Type.Kind(), val)
}
}
return val
}