Пример #1
0
func (no *NaiveOptimizer) TrySortMerge(plan planner.Plan) {
	last, curr := planner.FindNextPipelineComponentOfType(plan.Root.GetSource(), planner.JoinerType)
	if curr != nil {
		currJoiner := curr.(planner.Joiner)
		sortMergeJoiner := planner.NewOttoSortMergeJoiner()
		err := sortMergeJoiner.SetCondition(currJoiner.GetCondition())
		if err == nil {
			// now we need to make sure that the upstream sources can be sorted propertly
			leftSource := currJoiner.GetLeftSource()
			rightSource := currJoiner.GetRightSource()

			// FIXME for now this only works if the immidiate sources are datasources
			// needs to be made to work through joins and other pipeline components

			leftDataSource, isLeftDataSource := leftSource.(planner.DataSource)
			rightDataSource, isRightDataSource := rightSource.(planner.DataSource)
			if isLeftDataSource && isRightDataSource {
				if leftDataSource.GetOrderBy() == nil && rightDataSource.GetOrderBy() == nil {
					leftSort := parser.NewSortItem(parser.NewProperty(sortMergeJoiner.LeftExpr.SymbolsReferenced()[0]), true)
					err = leftDataSource.SetOrderBy(parser.SortList{*leftSort})
					if err != nil {
						//log.Printf("merge join not possible left datasource rejected order by")
						return
					}

					rightSort := parser.NewSortItem(parser.NewProperty(sortMergeJoiner.RightExpr.SymbolsReferenced()[0]), true)
					err = rightDataSource.SetOrderBy(parser.SortList{*rightSort})
					if err != nil {
						//log.Printf("merge join not possible right datasource rejected order by")
						return
					}

					//if we made it this far, it shoudl work
					//lets attach the left and right datasources to the new joiner
					sortMergeJoiner.SetLeftSource(leftDataSource)
					sortMergeJoiner.SetRightSource(rightDataSource)

					//now we just need to replace the existing joiner with the new one
					if last == nil {
						plan.Root.SetSource(sortMergeJoiner)
					} else {
						last.SetSource(sortMergeJoiner)
					}
				} else {
					//log.Printf("merge join optimization only supports direct datasources that are not already ordered")
				}
			} else {
				//log.Printf("merge join optimization only supports direct datasources before join")
			}
		} else {
			//log.Printf("merge join not going to work here %v", err)
		}
	}
}
Пример #2
0
func (no *NaiveOptimizer) MoveJoinConditionsUpTree(plan planner.Plan) {

	_, curr := planner.FindNextPipelineComponentOfType(plan.Root.GetSource(), planner.JoinerType)

	if curr != nil {
		currJoiner := curr.(planner.Joiner)
		//log.Printf("Expression considerered for separation is %#v", currJoiner.GetCondition())

		// we need to keep running this until it sep is nil
		joinCondition := currJoiner.GetCondition()
		if joinCondition != nil {
			sep, rest := LookForSeparableExpression(joinCondition)
			for sep != nil {

				//log.Printf("Sep Expression is %v", sep)
				//log.Printf("Rest Expression is %v", rest)

				// now try to place the separable expression
				sepSymbols := sep.SymbolsReferenced()
				if len(sepSymbols) > 0 {
					sepDataSource := sepSymbols[0]
					sepDotIndex := strings.Index(sepDataSource, ".")
					sepDs := sepDataSource[0:sepDotIndex]

					// find the datasource on the LHS
					_, leftDs := planner.FindNextPipelineComponentOfType(currJoiner.GetLeftSource(), planner.DataSourceType)
					if leftDs != nil {
						leftDataSource := leftDs.(planner.DataSource)
						if leftDataSource.GetAs() == sepDs {
							//log.Printf("this expression goes left")
							moved := MoveSeparableExpressionToDataSource(leftDataSource, currJoiner, sep, rest)
							if !moved {
								// as soon as we get to something we couldnt move, we stop trying
								return
							}
						}
					}

					// find the datasource on the RHS
					_, rightDs := planner.FindNextPipelineComponentOfType(currJoiner.GetRightSource(), planner.DataSourceType)
					if rightDs != nil {
						rightDataSource := rightDs.(planner.DataSource)
						if rightDataSource.GetAs() == sepDs {
							//log.Printf("this expression goes right")
							moved := MoveSeparableExpressionToDataSource(rightDataSource, currJoiner, sep, rest)
							if !moved {
								// as soon as we get to something we couldnt move, we stop trying
								return
							}
						}
					}

				}

				joinCondition = currJoiner.GetCondition()
				sep, rest = LookForSeparableExpression(joinCondition)
			}
		}
	}

}