Exemple #1
0
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)
	}
}
Exemple #2
0
	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")),
Exemple #3
0
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}

}
Exemple #4
0
Fichier : y.go Projet : mschoch/tuq
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 */
}