func (m *JobBuilder) VisitJoin(from *expr.SqlSource) (expr.Task, error) { u.Debugf("VisitJoin %s", from.Source) //u.Debugf("from.Name:'%v' : %v", from.Name, from.Source.String()) source := m.schema.Conn(from.SourceName()) //u.Debugf("left source: %T", source) // Must provider either Scanner, SourcePlanner, Seeker interfaces if sourcePlan, ok := source.(datasource.SourcePlanner); ok { // This is flawed, visitor pattern would have you pass in a object which implements interface // but is one of many different objects that implement that interface so that the // Accept() method calls the apppropriate method u.Warnf("SourcePlanner????") scanner, err := sourcePlan.Accept(NewSourcePlan(from)) if err == nil { return NewSourceJoin(from, scanner), nil } u.Errorf("Could not source plan for %v %T %#v", from.Name, source, source) } scanner, ok := source.(datasource.Scanner) if !ok { u.Errorf("Could not create scanner for %v %T %#v", from.Name, source, source) return nil, fmt.Errorf("Must Implement Scanner") } if err := buildColIndex(scanner, from); err != nil { return nil, err } return NewSourceJoin(from, scanner), nil }