github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/internal/valuer/reflect.go (about)

     1  // Copyright 2021 ecodeclub
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package valuer
    16  
    17  import (
    18  	"reflect"
    19  
    20  	"github.com/ecodeclub/eorm/internal/rows"
    21  
    22  	"github.com/ecodeclub/eorm/internal/errs"
    23  	"github.com/ecodeclub/eorm/internal/model"
    24  )
    25  
    26  var _ Creator = NewReflectValue
    27  
    28  // reflectValue 基于反射的 Value
    29  type reflectValue struct {
    30  	val  reflect.Value
    31  	meta *model.TableMeta
    32  }
    33  
    34  // NewReflectValue 返回一个封装好的,基于反射实现的 Value
    35  // 输入 val 必须是一个指向结构体实例的指针,而不能是任何其它类型
    36  func NewReflectValue(val interface{}, meta *model.TableMeta) Value {
    37  	return reflectValue{
    38  		val:  reflect.ValueOf(val).Elem(),
    39  		meta: meta,
    40  	}
    41  }
    42  
    43  // Field 返回字段值
    44  func (r reflectValue) Field(name string) (reflect.Value, error) {
    45  	res, ok := r.fieldByIndex(name)
    46  	if !ok {
    47  		return reflect.Value{}, errs.NewInvalidFieldError(name)
    48  	}
    49  	return res, nil
    50  }
    51  
    52  func (r reflectValue) fieldByIndex(name string) (reflect.Value, bool) {
    53  	cm, ok := r.meta.FieldMap[name]
    54  	if !ok {
    55  		return reflect.Value{}, false
    56  	}
    57  	value := r.val
    58  	for _, i := range cm.FieldIndexes {
    59  		value = value.Field(i)
    60  	}
    61  	return value, true
    62  }
    63  
    64  func (r reflectValue) SetColumns(rows rows.Rows) error {
    65  	cs, err := rows.Columns()
    66  	if err != nil {
    67  		return err
    68  	}
    69  	if len(cs) > len(r.meta.Columns) {
    70  		return errs.ErrTooManyColumns
    71  	}
    72  
    73  	// TODO 性能优化
    74  	// colValues 和 colEleValues 实质上最终都指向同一个对象
    75  	colValues := make([]interface{}, len(cs))
    76  	colEleValues := make([]reflect.Value, len(cs))
    77  
    78  	for i, c := range cs {
    79  		cm, ok := r.meta.ColumnMap[c]
    80  		if !ok {
    81  			return errs.NewInvalidColumnError(c)
    82  		}
    83  		val := reflect.New(cm.Typ)
    84  		colValues[i] = val.Interface()
    85  		colEleValues[i] = val.Elem()
    86  	}
    87  
    88  	if err = rows.Scan(colValues...); err != nil {
    89  		return err
    90  	}
    91  
    92  	for i, c := range cs {
    93  		cm := r.meta.ColumnMap[c]
    94  		fd, _ := r.fieldByIndex(cm.FieldName)
    95  		fd.Set(colEleValues[i])
    96  	}
    97  	return nil
    98  }