func MoveSeparableExpressionToDataSource(dataSource planner.DataSource, joiner planner.Joiner, sep parser.Expression, rest parser.Expression) bool { newFilterExpression := sep // get the existing filter (if any) filterExpression := dataSource.GetFilter() if filterExpression != nil { // build an AND expression with sep and the existing newFilterExpression = parser.NewAndExpression(sep, filterExpression) } err := dataSource.SetFilter(newFilterExpression) if err != nil { // this data source doesn't support this filter // continue once this becomes a loop //log.Printf("Datasource rejected the new filter expression, %v", err) return false } else { // it accepted the filter, now we just updated the join condition err := joiner.SetCondition(rest) if err != nil { // hmmn, now joiner rejected its new condition // we must back out the other change //log.Printf("Datasource accepted, but now joiner rejected new filter expression, trying to reset") err := dataSource.SetFilter(filterExpression) if err != nil { log.Fatalf("Datasource rejected setting its filter back to the original value, I don't know what to do") } return false } } return true }
func LookForSeparableExpression(expr parser.Expression) (parser.Expression, parser.Expression) { count := NumberOfDataSourcesReferencedInExpression(expr) if count < 2 { // all symbols in this expression refer to the same datasource // it could be moved out return expr, nil } else { // this expression refers to symbols in 2 or more datasources // it cannot be moved itself, but we may have to consier sub-expressions and_expr, ok := expr.(*parser.AndExpression) if ok { // this expression is an AND expression so we can consider moving out // its pieces sep, remaining := LookForSeparableExpression(and_expr.Left) if sep != nil { // we found someting to remove if remaining == nil { // nothing remaining, return RHS return sep, and_expr.Right } else { // build a new AND expression with the remaining piece and the RHS return sep, parser.NewAndExpression(remaining, and_expr.Right) } } else { // didn't find anything to remove, try the RHS sep, remaining := LookForSeparableExpression(and_expr.Right) if sep != nil { // we found someting to remove if remaining == nil { // nothing left, return LHS return sep, and_expr.Left } else { // build a new AND expression with the remaining piece and the RHS return sep, parser.NewAndExpression(and_expr.Left, remaining) } } } } } // not an AND expression, nothing more we can do return nil, nil }
var oneSymbolExpressions = []parser.Expression{ parser.NewProperty("bob"), parser.NewArrayLiteral(parser.ExpressionList{parser.NewProperty("bob")}), parser.NewObjectLiteral(parser.Object{"field": parser.NewProperty("bob")}), parser.NewNotExpression(parser.NewProperty("bob")), parser.NewBracketMemberExpression(parser.NewProperty("bob"), parser.NewIntegerLiteral(0)), } var twoSymbolExpressions = []parser.Expression{ parser.NewPlusExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewMinusExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewMultiplyExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewDivideExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewOrExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewAndExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewLessThanExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewLessThanOrEqualExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewGreaterThanExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewGreaterThanOrEqualExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewEqualsExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), parser.NewNotEqualsExpression(parser.NewProperty("bob"), parser.NewProperty("jay")), } var threeSymbolExpressions = []parser.Expression{ parser.NewTernaryExpression(parser.NewProperty("bob"), parser.NewProperty("jay"), parser.NewProperty("cat")), } func TestSymbolsReferenced(t *testing.T) { for _, v := range zeroSymbolExpressions {
func yyParse(yylex yyLexer) int { var yyn int var yylval yySymType var yyVAL yySymType yyS := make([]yySymType, yyMaxDepth) Nerrs := 0 /* number of errors */ Errflag := 0 /* error recovery flag */ yystate := 0 yychar := -1 yyp := -1 goto yystack ret0: return 0 ret1: return 1 yystack: /* put a state and value onto the stack */ if yyDebug >= 4 { fmt.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate)) } yyp++ if yyp >= len(yyS) { nyys := make([]yySymType, len(yyS)*2) copy(nyys, yyS) yyS = nyys } yyS[yyp] = yyVAL yyS[yyp].yys = yystate yynewstate: yyn = yyPact[yystate] if yyn <= yyFlag { goto yydefault /* simple state */ } if yychar < 0 { yychar = yylex1(yylex, &yylval) } yyn += yychar if yyn < 0 || yyn >= yyLast { goto yydefault } yyn = yyAct[yyn] if yyChk[yyn] == yychar { /* valid shift */ yychar = -1 yyVAL = yylval yystate = yyn if Errflag > 0 { Errflag-- } goto yystack } yydefault: /* default state action */ yyn = yyDef[yystate] if yyn == -2 { if yychar < 0 { yychar = yylex1(yylex, &yylval) } /* look through exception table */ xi := 0 for { if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { break } xi += 2 } for xi += 2; ; xi += 2 { yyn = yyExca[xi+0] if yyn < 0 || yyn == yychar { break } } yyn = yyExca[xi+1] if yyn < 0 { goto ret0 } } if yyn == 0 { /* error ... attempt to resume parsing */ switch Errflag { case 0: /* brand new error */ yylex.Error("syntax error") Nerrs++ if yyDebug >= 1 { fmt.Printf("%s", yyStatname(yystate)) fmt.Printf("saw %s\n", yyTokname(yychar)) } fallthrough case 1, 2: /* incompletely recovered error ... try again */ Errflag = 3 /* find a state where "error" is a legal shift action */ for yyp >= 0 { yyn = yyPact[yyS[yyp].yys] + yyErrCode if yyn >= 0 && yyn < yyLast { yystate = yyAct[yyn] /* simulate a shift of "error" */ if yyChk[yystate] == yyErrCode { goto yystack } } /* the current p has no shift on "error", pop stack */ if yyDebug >= 2 { fmt.Printf("error recovery pops state %d\n", yyS[yyp].yys) } yyp-- } /* there is no state on the stack with an error shift ... abort */ goto ret1 case 3: /* no shift yet; clobber input char */ if yyDebug >= 2 { fmt.Printf("error recovery discards %s\n", yyTokname(yychar)) } if yychar == yyEofCode { goto ret1 } yychar = -1 goto yynewstate /* try again in the same state */ } } /* reduction by production yyn */ if yyDebug >= 2 { fmt.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) } yynt := yyn yypt := yyp _ = yypt // guard against "declared and not used" yyp -= yyR2[yyn] yyVAL = yyS[yyp+1] /* consult goto table to find next state */ yyn = yyR1[yyn] yyg := yyPgo[yyn] yyj := yyg + yyS[yyp].yys + 1 if yyj >= yyLast { yystate = yyAct[yyg] } else { yystate = yyAct[yyj] if yyChk[yystate] != -yyn { yystate = yyAct[yyg] } } // dummy call; replaced with literal code switch yynt { case 1: //line tuql.y:36 { logDebugGrammar("INPUT") } case 3: //line tuql.y:40 { logDebugGrammar("PRAGMA: %v", yyS[yypt-3]) right := parsingStack.Pop() left := parsingStack.Pop() parser.ProcessPragma(left.(parser.Expression), right.(parser.Expression)) } case 4: //line tuql.y:47 { logDebugGrammar("SELECT_STMT") parsingQuery.ParsedSuccessfully = true } case 6: //line tuql.y:52 { parsingQuery.IsExplainOnly = true } case 12: //line tuql.y:64 { thisExpression := parsingStack.Pop() parsingQuery.Limit = thisExpression.(parser.Expression) } case 13: //line tuql.y:69 { thisExpression := parsingStack.Pop() parsingQuery.Offset = thisExpression.(parser.Expression) } case 16: //line tuql.y:78 { thisExpression := parser.NewSortItem(parsingStack.Pop().(parser.Expression), true) parsingQuery.Orderby = append(parsingQuery.Orderby, *thisExpression) } case 17: //line tuql.y:81 { thisExpression := parser.NewSortItem(parsingStack.Pop().(parser.Expression), true) parsingQuery.Orderby = append(parsingQuery.Orderby, *thisExpression) } case 18: //line tuql.y:84 { thisExpression := parser.NewSortItem(parsingStack.Pop().(parser.Expression), false) parsingQuery.Orderby = append(parsingQuery.Orderby, *thisExpression) } case 19: //line tuql.y:89 { logDebugGrammar("SELECT_COMPOUND") } case 25: //line tuql.y:99 { logDebugGrammar("SELECT_CORE") } case 26: //line tuql.y:102 { logDebugGrammar("SELECT GROUP") parsingQuery.IsAggregateQuery = true parsingQuery.Groupby = parsingStack.Pop().(parser.ExpressionList) } case 27: //line tuql.y:107 { logDebugGrammar("SELECT GROUP HAVING - EMPTY") } case 28: //line tuql.y:108 { logDebugGrammar("SELECT GROUP HAVING - SELECT GROUP") } case 29: //line tuql.y:109 { logDebugGrammar("SELECT GROUP HAVING - SELECT GROUP SELECT HAVING") } case 30: //line tuql.y:114 { parsingQuery.Having = parsingStack.Pop().(parser.Expression) } case 31: //line tuql.y:117 { logDebugGrammar("SELECT WHERE - EMPTY") } case 32: //line tuql.y:118 { logDebugGrammar("SELECT WHERE - EXPR") where_part := parsingStack.Pop() parsingQuery.Where = where_part.(parser.Expression) } case 34: //line tuql.y:124 { logDebugGrammar("SELECT_FROM") } case 37: //line tuql.y:131 { ds := parser.NewDataSource(yyS[yypt-0].s) parsingQuery.AddDataSource(ds) } case 38: //line tuql.y:134 { ds := parser.NewDataSource(yyS[yypt-1].s) nextOver := parsingStack.Pop() for nextOver != nil { ds.AddOver(nextOver.(*parser.Over)) nextOver = parsingStack.Pop() } parsingQuery.AddDataSource(ds) } case 39: //line tuql.y:142 { ds := parser.NewDataSourceWithAs(yyS[yypt-2].s, yyS[yypt-0].s) parsingQuery.AddDataSource(ds) } case 40: //line tuql.y:145 { ds := parser.NewDataSourceWithAs(yyS[yypt-3].s, yyS[yypt-1].s) nextOver := parsingStack.Pop() for nextOver != nil { ds.AddOver(nextOver.(*parser.Over)) nextOver = parsingStack.Pop() } parsingQuery.AddDataSource(ds) } case 43: //line tuql.y:159 { prop := parsingStack.Pop().(*parser.Property) over := parser.NewOver(prop, yyS[yypt-0].s) parsingStack.Push(over) } case 45: //line tuql.y:167 { logDebugGrammar("SELECT_SELECT") } case 46: //line tuql.y:170 { logDebugGrammar("SELECT_SELECT_HEAD") } case 49: //line tuql.y:175 { logDebugGrammar("SELECT SELECT TAIL - EMPTY") } case 50: //line tuql.y:176 { logDebugGrammar("SELECT SELECT TAIL - EXPR") thisExpression := parsingStack.Pop() parsingQuery.Sel = thisExpression.(parser.Expression) } case 51: //line tuql.y:182 { logDebugGrammar("EXPRESSION") } case 52: //line tuql.y:183 { logDebugGrammar("EXPRESSION - TERNARY") elsee := parsingStack.Pop().(parser.Expression) thenn := parsingStack.Pop().(parser.Expression) iff := parsingStack.Pop().(parser.Expression) thisExpr := parser.NewTernaryExpression(iff, thenn, elsee) parsingStack.Push(thisExpr) } case 53: //line tuql.y:192 { logDebugGrammar("EXPR - PLUS") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewPlusExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 54: //line tuql.y:198 { logDebugGrammar("EXPR - MINUS") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewMinusExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 55: //line tuql.y:204 { logDebugGrammar("EXPR - MULT") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewMultiplyExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 56: //line tuql.y:210 { logDebugGrammar("EXPR - DIV") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewDivideExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 57: //line tuql.y:216 { logDebugGrammar("EXPR - AND") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewAndExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 58: //line tuql.y:222 { logDebugGrammar("EXPR - OR") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewOrExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 59: //line tuql.y:228 { logDebugGrammar("EXPR - EQ") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewEqualsExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 60: //line tuql.y:234 { logDebugGrammar("EXPR - LT") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewLessThanExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 61: //line tuql.y:240 { logDebugGrammar("EXPR - LTE") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewLessThanOrEqualExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 62: //line tuql.y:246 { logDebugGrammar("EXPR - GT") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewGreaterThanExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 63: //line tuql.y:252 { logDebugGrammar("EXPR - GTE") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewGreaterThanOrEqualExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 64: //line tuql.y:258 { logDebugGrammar("EXPR - NE") right := parsingStack.Pop() left := parsingStack.Pop() thisExpression := parser.NewNotEqualsExpression(left.(parser.Expression), right.(parser.Expression)) parsingStack.Push(thisExpression) } case 67: //line tuql.y:269 { logDebugGrammar("EXPR - NOT") curr := parsingStack.Pop().(parser.Expression) thisExpression := parser.NewNotExpression(curr) parsingStack.Push(thisExpression) } case 69: //line tuql.y:277 { logDebugGrammar("SUFFIX_EXPR") } case 70: //line tuql.y:280 { logDebugGrammar("NULL") thisExpression := parser.NewNull() parsingStack.Push(thisExpression) } case 71: //line tuql.y:284 { } case 72: //line tuql.y:285 { logDebugGrammar("ATOM - prop[]") rightExpr := parsingStack.Pop().(parser.Expression) leftProp := parsingStack.Pop().(*parser.Property) thisExpression := parser.NewBracketMemberExpression(leftProp, rightExpr) parsingStack.Push(thisExpression) } case 73: //line tuql.y:291 { thisExpression := parser.NewIntegerLiteral(yyS[yypt-0].n) parsingStack.Push(thisExpression) } case 74: //line tuql.y:293 { thisExpression := parser.NewIntegerLiteral(-yyS[yypt-1].n) parsingStack.Push(thisExpression) } case 75: //line tuql.y:295 { thisExpression := parser.NewFloatLiteral(yyS[yypt-0].f) parsingStack.Push(thisExpression) } case 76: //line tuql.y:297 { thisExpression := parser.NewFloatLiteral(-yyS[yypt-1].f) parsingStack.Push(thisExpression) } case 77: //line tuql.y:299 { thisExpression := parser.NewStringLiteral(yyS[yypt-0].s) parsingStack.Push(thisExpression) } case 78: //line tuql.y:301 { thisExpression := parser.NewBoolLiteral(true) parsingStack.Push(thisExpression) } case 79: //line tuql.y:303 { thisExpression := parser.NewBoolLiteral(false) parsingStack.Push(thisExpression) } case 80: //line tuql.y:305 { logDebugGrammar("ATOM - {}") } case 81: //line tuql.y:307 { logDebugGrammar("ATOM - []") exp_list := parsingStack.Pop().(parser.ExpressionList) thisExpression := parser.NewArrayLiteral(exp_list) parsingStack.Push(thisExpression) } case 82: //line tuql.y:312 { logDebugGrammar("FUNCTION - $1.s") exp_list := parsingStack.Pop().(parser.ExpressionList) function := parsingStack.Pop().(*parser.Function) function.AddArguments(exp_list) parsingStack.Push(function) } case 85: //line tuql.y:322 { logDebugGrammar("EXPRESSION_LIST - EXPRESSION") exp_list := make(parser.ExpressionList, 0) exp_list = append(exp_list, parsingStack.Pop().(parser.Expression)) parsingStack.Push(exp_list) } case 86: //line tuql.y:327 { logDebugGrammar("EXPRESSION_LIST - EXPRESSION COMMA EXPRESSION_LIST") rest := parsingStack.Pop().(parser.ExpressionList) last := parsingStack.Pop() new_list := make(parser.ExpressionList, 0) new_list = append(new_list, last.(parser.Expression)) for _, v := range rest { new_list = append(new_list, v) } parsingStack.Push(new_list) } case 88: //line tuql.y:340 { last := parsingStack.Pop().(*parser.ObjectLiteral) rest := parsingStack.Pop().(*parser.ObjectLiteral) rest.AddAll(last) parsingStack.Push(rest) } case 89: //line tuql.y:347 { thisKey := yyS[yypt-2].s thisValue := parsingStack.Pop().(parser.Expression) thisExpression := parser.NewObjectLiteral(parser.Object{thisKey: thisValue}) parsingStack.Push(thisExpression) } case 90: //line tuql.y:354 { thisExpression := parser.NewProperty(yyS[yypt-0].s) parsingStack.Push(thisExpression) } case 91: //line tuql.y:358 { thisValue := parsingStack.Pop().(*parser.Property) thisExpression := parser.NewProperty(yyS[yypt-2].s + "." + thisValue.Symbol) parsingStack.Push(thisExpression) } case 92: //line tuql.y:365 { parsingQuery.IsAggregateQuery = true thisExpression := parser.NewFunction("min") parsingStack.Push(thisExpression) } case 93: //line tuql.y:370 { parsingQuery.IsAggregateQuery = true thisExpression := parser.NewFunction("max") parsingStack.Push(thisExpression) } case 94: //line tuql.y:375 { parsingQuery.IsAggregateQuery = true thisExpression := parser.NewFunction("avg") parsingStack.Push(thisExpression) } case 95: //line tuql.y:380 { parsingQuery.IsAggregateQuery = true thisExpression := parser.NewFunction("count") parsingStack.Push(thisExpression) } case 96: //line tuql.y:385 { parsingQuery.IsAggregateQuery = true thisExpression := parser.NewFunction("sum") parsingStack.Push(thisExpression) } } goto yystack /* stack new state and value */ }