首先我们需要给原来代码打个补丁,在SelectScan 结构体初始化时需要传入 UpdateScan 接口对象,但很多时候我们需要传入的是 Scan 对象,因此我们需要做一个转换,也就是当初始化 SelectScan 时,如果传入的是 Scan 对象,那么我们就将其封装成 UpdateScan 接口对象,因此在 query 目录下增加一个名为 updatescan_wrapper.go 的文件,在其中输入内容如下:
package query
import (
"record_manager"
)
type UpdateScanWrapper struct {
scan Scan
}
func NewUpdateScanWrapper(s Scan) *UpdateScanWrapper {
return &UpdateScanWrapper{
scan: s,
}
}
func (u *UpdateScanWrapper) GetScan() Scan {
return u.scan
}
func (u *UpdateScanWrapper) SetInt(fldName string, val int) {
//DO NOTHING
}
func (u *UpdateScanWrapper) SetString(fldName string, val string) {
//DO NOTHING
}
func (u *UpdateScanWrapper) SetVal(fldName string, val *Constant) {
//DO NOTHING
}
func (u *UpdateScanWrapper) Insert() {
//DO NOTHING
}
func (u *UpdateScanWrapper) Delete() {
//DO NOTHING
}
func (u *UpdateScanWrapper) GetRid() *record_manager.RID {
return nil
}
func (u *UpdateScanWrapper) MoveToRid(rid *record_manager.RID) {
// DO NOTHING
}
上面代码逻辑简单,如果调用 Scan 对象接口时,他直接调用其 Scan 内部对象的接口,如果调用到 UpdateScan 的接口,那么它什么都不做。完成上面代码后,我们在select_plan.go 中进行一些修改:
func (s *SelectPlan) Open() interface{} {
scan := s.p.Open()
updateScan, ok := scan.(query.UpdateScan)
if !ok {
updateScanWrapper := query.NewUpdateScanWrapper(scan.(query.Scan))
return query.NewSelectionScan(updateScanWrapper, s.pred)
}
return query.NewSelectionScan(updateScan, s.pred)
}
上面代码在创建 SelectScan 对象时,先判断传进来的对象是否能类型转换为 UpdateScan,如果不能,那意味着s.p.Open 获取的是 Scan 对象,因此我们使用前面的代码封装一下再用来创建 SelectScan 对象。完