func TestCartesianProductJoiner(t *testing.T) { ds1 := NewStubDataSource("stub", "stub1") ds2 := NewStubDataSource("stub", "stub2") j := NewOttoCartesianProductJoiner() j.SetLeftSource(ds1) j.SetRightSource(ds2) j.SetCondition(parser.NewBoolLiteral(true)) go j.Run() output := j.GetDocumentChannel() rows := 0 for doc := range output { rows += 1 _, lok := doc["stub1"] _, rok := doc["stub2"] if !lok || !rok { t.Errorf("Expected row to contain stub1 and stub2") } } if rows != 36 { t.Errorf("Expected 36 rows from full cartesian product, got %v", rows) } }
for _, v := range invalidQueries { _, err := tuqlParser.Parse(v) if err == nil { t.Errorf("Invalid Query Parsed Successfully: %v - %v", v, err) } } } var zeroSymbolExpressions = []parser.Expression{ parser.NewIntegerLiteral(7), parser.NewFloatLiteral(5.5), parser.NewNull(), parser.NewStringLiteral("name"), parser.NewBoolLiteral(true), } 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")),
func (np *NaivePlanner) Plan(query parser.Select) []planner.Plan { result := planner.Plan{} var last_in_pipeline planner.PlanPipelineComponent // from for _, datasource := range query.From { // look up the data source ds := datasources.NewDataSourceWithName(datasource.Def) if ds == nil { log.Printf("No such datasource exists") return nil } ds.SetName(datasource.Def) ds.SetAs(datasource.As) // handle any overs var lastthis planner.PlanPipelineComponent lastthis = ds for _, v := range datasource.Overs { over := planner.NewOttoOver() over.SetPath(v.Path) over.SetAs(v.As) over.SetSource(lastthis) lastthis = over } if last_in_pipeline != nil { joiner := planner.NewOttoCartesianProductJoiner() joiner.SetLeftSource(last_in_pipeline) joiner.SetRightSource(lastthis) last_in_pipeline = joiner } else { last_in_pipeline = lastthis } } // where if query.Where != nil { ottoFilter := planner.NewOttoFilter() ottoFilter.SetSource(last_in_pipeline) ottoFilter.SetFilter(query.Where) last_in_pipeline = ottoFilter } if query.IsAggregateQuery { // in an aggregate query we sometimes need to collect stats // on fields that we're not aggregating on // the full list will be the symbols from the SELECT clause // invalid entries should have been detected earlier // (columns not in the group by clause and not inside an aggregate function) stat_fields := make([]string, 0) if query.Sel != nil { stat_fields = query.Sel.SymbolsReferenced() } // group by if query.Groupby != nil { ottoGrouper := planner.NewOttoGrouper() ottoGrouper.SetGroupByWithStatsFields(query.Groupby, stat_fields) ottoGrouper.SetSource(last_in_pipeline) last_in_pipeline = ottoGrouper } else { // easy to overlook, but if they use aggregate functions // this is aggregate query, even though they didnt explicitly // have a group by clause, we should apply a default group by // clause that groups everything ottoGrouper := planner.NewOttoGrouper() ottoGrouper.SetGroupByWithStatsFields(parser.ExpressionList{parser.NewBoolLiteral(true)}, stat_fields) ottoGrouper.SetSource(last_in_pipeline) last_in_pipeline = ottoGrouper } // having if query.Having != nil { ottoFilter := planner.NewOttoFilter() ottoFilter.SetSource(last_in_pipeline) ottoFilter.SetFilter(query.Having) last_in_pipeline = ottoFilter } } // order by if query.Orderby != nil { ottoOrderer := planner.NewOttoOrderer() ottoOrderer.SetSource(last_in_pipeline) ottoOrderer.SetOrderBy(query.Orderby) last_in_pipeline = ottoOrderer } // offset if query.Offset != nil { offset := planner.NewOttoOffsetter() offset.SetOffset(query.Offset) offset.SetSource(last_in_pipeline) last_in_pipeline = offset } // limit if query.Limit != nil { limit := planner.NewOttoLimitter() limit.SetLimit(query.Limit) limit.SetSource(last_in_pipeline) last_in_pipeline = limit } // select if query.Sel != nil { ottoSelecter := planner.NewOttoSelecter() ottoSelecter.SetSource(last_in_pipeline) ottoSelecter.SetSelect(query.Sel) result.Root = ottoSelecter } else { defaultSelecter := planner.NewDefaultSelecter() defaultSelecter.SetSource(last_in_pipeline) result.Root = defaultSelecter } return []planner.Plan{result} }
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 */ }