// Copyright © 2016 Abcum Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package item import ( "time" "github.com/imdario/mergo" "github.com/abcum/surreal/sql" "github.com/abcum/surreal/util/data" ) func (this *Doc) Merge(data sql.Expr) (err error) { if err = this.setFld(); err != nil { return } if err = this.defFld(); err != nil { return } if err = this.setFld(); err != nil { return } switch expr := data.(type) { case *sql.DataExpression: this.mrgSet(expr) case *sql.DiffExpression: this.mrgDpm(expr) case *sql.MergeExpression: this.mrgAny(expr) case *sql.ContentExpression: this.mrgAll(expr) } if err = this.setFld(); err != nil { return } if err = this.mrgFld(); err != nil { return } if err = this.setFld(); err != nil { return } return } func (this *Doc) setFld() (err error) { this.current.Set(this.id, "id") this.current.Set(this.key.ID, "meta.id") this.current.Set(this.key.TB, "meta.tb") return } func (this *Doc) defFld() (err error) { for _, fld := range this.fields { this.current.Walk(func(key string, val interface{}) error { v := this.current.Valid(key) e := this.current.Exists(key) if fld.Default != nil && (!e || !v && fld.Notnull) { switch val := fld.Default.(type) { case sql.Void, *sql.Void: this.current.Del(key) case sql.Null, *sql.Null: this.current.Set(nil, key) default: this.current.Set(fld.Default, key) case sql.Ident: this.current.Set(this.current.Get(val.ID).Data(), key) case *sql.Ident: this.current.Set(this.current.Get(val.ID).Data(), key) } } return nil }, fld.Name.String()) } return } func (this *Doc) mrgFld() (err error) { for _, fld := range this.fields { if err = this.each(fld); err != nil { return } } return } func (this *Doc) mrgAll(expr *sql.ContentExpression) { switch val := expr.Data.(type) { case sql.Object: this.current = data.Consume(map[string]interface{}(val)) case map[string]interface{}: this.current = data.Consume(map[string]interface{}(val)) case *sql.Param: switch val := this.runtime.Get(val.ID).Data().(type) { case sql.Object: this.current = data.Consume(map[string]interface{}(val)) case map[string]interface{}: this.current = data.Consume(map[string]interface{}(val)) } } } func (this *Doc) mrgAny(expr *sql.MergeExpression) { lhs, _ := this.current.Data().(map[string]interface{}) rhs, _ := expr.Data.(map[string]interface{}) err := mergo.MapWithOverwrite(&lhs, rhs) if err != nil { return } this.current = data.Consume(lhs) } func (this *Doc) mrgDpm(expr *sql.DiffExpression) { } func (this *Doc) mrgSet(expr *sql.DataExpression) { for _, part := range expr.Data { lhs := this.getMrgItemLHS(part.LHS) rhs := this.getMrgItemRHS(part.RHS) if part.Op == sql.EQ { switch part.RHS.(type) { default: this.current.Set(rhs, lhs) case *sql.Void: this.current.Del(lhs) } } if part.Op == sql.INC { this.current.Inc(rhs, lhs) } if part.Op == sql.DEC { this.current.Dec(rhs, lhs) } } } func (this *Doc) getMrgItemLHS(expr sql.Expr) string { switch val := expr.(type) { default: return "" case sql.Ident: return val.ID case *sql.Ident: return val.ID } } func (this *Doc) getMrgItemRHS(expr sql.Expr) interface{} { switch val := expr.(type) { default: return nil case time.Time: return val case bool, int64, float64, string: return val case []interface{}, map[string]interface{}: return val case *sql.Thing: return val case *sql.Param: return this.runtime.Get(val.ID).Data() case *sql.Ident: return this.current.Get(val.ID).Data() } }