Example #1
0
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
}
Example #2
0
func buildColIndex(sourceConn datasource.SourceConn, from *expr.SqlSource) error {

	if from.Source == nil {
		return nil
	}
	colSchema, ok := sourceConn.(datasource.SchemaColumns)
	if !ok {
		u.Errorf("Could not create column Schema for %v  %T %#v", from.Name, sourceConn, sourceConn)
		return fmt.Errorf("Must Implement SchemaColumns")
	}
	from.BuildColIndex(colSchema.Columns())
	return nil
}
Example #3
0
func (m *JobBuilder) VisitSubselect(from *expr.SqlSource) (expr.Task, error) {

	if from.Source != nil {
		u.Debugf("VisitSubselect from.source = %q", from.Source)
	} else {
		u.Debugf("VisitSubselect from=%q", from)
	}

	tasks := make(Tasks, 0)
	needsJoinKey := false

	switch {

	case from.Name != "" && from.Source == nil:
		// If we have table name and no Source(sub-query/join-query) then just read source

		sourceConn := m.schema.Conn(from.Name)
		u.Debugf("sourceConn: tbl:%q   %T  %#v", from.Name, sourceConn, sourceConn)
		// Must provider either Scanner, SourcePlanner, Seeker interfaces
		if sourcePlan, ok := sourceConn.(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 NewSource(from, scanner), nil
			}
			u.Errorf("Could not source plan for %v  %T %#v", from.Name, sourceConn, sourceConn)
		}

		scanner, hasScanner := sourceConn.(datasource.Scanner)
		if !hasScanner {
			return nil, fmt.Errorf("%T Must Implement Scanner for %q", sourceConn, from.String())
		}
		if err := buildColIndex(scanner, from); err != nil {
			return nil, err
		}
		sourceTask := NewSource(from, scanner)
		tasks.Add(sourceTask)

	case from.Source != nil && len(from.JoinNodes()) > 0:
		// This is a source that is part of a join expression
		joinSource, err := m.VisitJoin(from)
		if err != nil {
			return nil, err
		}
		tasks.Add(joinSource.(TaskRunner))
		needsJoinKey = true

	case from.Source != nil && len(from.JoinNodes()) == 0:
		// Sub-Query

		sourceConn := m.schema.Conn(from.Name)
		u.Debugf("SubQuery?: %s  join:%#v  JoinNodes:%#v", from.Source, from.JoinExpr, from.JoinNodes())
		// Must provider either Scanner, SourcePlanner, Seeker interfaces
		if sourcePlan, ok := sourceConn.(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 NewSource(from, scanner), nil
			}
			u.Errorf("Could not source plan for %v  %T %#v", from.Name, sourceConn, sourceConn)
		}

		scanner, ok := sourceConn.(datasource.Scanner)
		if !ok {
			u.Errorf("Could not create scanner for %v  %T %#v", from.Name, sourceConn, sourceConn)
			return nil, fmt.Errorf("Must Implement Scanner")
		}
		if err := buildColIndex(scanner, from); err != nil {
			return nil, err
		}
		sourceTask := NewSource(from, scanner)
		tasks.Add(sourceTask)

	default:
		u.Warnf("Not able to understand subquery? %s", from.String())
		return nil, expr.ErrNotImplemented
	}

	if from.Source != nil && from.Source.Where != nil {
		switch {
		case from.Source.Where.Expr != nil:
			//u.Debugf("adding where: %q", from.Source.Where.Expr)
			where := NewWhereFilter(from.Source.Where.Expr, from.Source)
			tasks.Add(where)
		default:
			u.Warnf("Found un-supported where type: %#v", from.Source)
			return nil, fmt.Errorf("Unsupported Where clause:  %q", from)
		}
	}

	if needsJoinKey {
		joinKeyTask, err := NewJoinKey(from, m.schema)
		if err != nil {
			return nil, err
		}
		tasks.Add(joinKeyTask)
	}
	// Plan?   Parallel?  hash?
	return NewSequential("sub-select", tasks), nil
}