예제 #1
0
func (m *Upsert) insertRows(ctx *Context, rows [][]*expr.ValueColumn) error {

	for _, row := range rows {
		//u.Infof("In Insert Scanner iter %#v", row)
		select {
		case <-m.SigChan():
			return nil
		default:
			vals := make([]driver.Value, len(row))
			for x, val := range row {
				if val.Expr != nil {
					exprVal, ok := vm.Eval(nil, val.Expr)
					if !ok {
						u.Errorf("Could not evaluate: %v", val.Expr)
						return fmt.Errorf("Could not evaluate expression: %v", val.Expr)
					}
					vals[x] = exprVal.Value()
				} else {
					vals[x] = val.Value.Value()
				}

				//u.Debugf("%d col: %v   vals:%v", x, val, vals[x])
			}
			if _, err := m.db.Put(ctx, nil, vals); err != nil {
				u.Errorf("Could not put values: %v", err)
				return err
			}
			// continue
		}
	}
	return nil
}
예제 #2
0
func joinValue(ctx *Context, node expr.Node, msg datasource.Message) (string, bool) {

	if msg == nil {
		u.Warnf("got nil message?")
	}
	if msgReader, ok := msg.Body().(expr.ContextReader); ok {

		joinVal, ok := vm.Eval(msgReader, node)
		//u.Debugf("msg: %#v", msgReader)
		//u.Infof("evaluating: ok?%v T:%T result=%v node expr:%v", ok, joinVal, joinVal.ToString(), node.StringAST())
		if !ok {
			u.Errorf("could not evaluate: %v", msg)
			return "", false
		}
		switch val := joinVal.(type) {
		case value.StringValue:
			return val.Val(), true
		default:
			u.Warnf("unknown type? %T", joinVal)
		}
	} else {
		u.Errorf("could not convert to message reader: %T", msg.Body())
	}
	return "", false
}
예제 #3
0
func evalSetExpression(col *rel.CommandColumn, ctx expr.ContextReadWriter, arg expr.Node) error {

	switch bn := arg.(type) {
	case *expr.BinaryNode:
		_, ok := bn.Args[0].(*expr.IdentityNode)
		if !ok {
			u.Warnf("expected identity but got %T in %s", bn.Args[0], arg.String())
			return fmt.Errorf("Expected identity but got %T", bn.Args[0])
		}
		rhv, ok := vm.Eval(ctx, bn.Args[1])
		if !ok {
			u.Warnf("expected right side value but got %T in %s", bn.Args[1], arg.String())
			return fmt.Errorf("Expected value but got %T", bn.Args[1])
		}
		//u.Infof(`writeContext.Put("%v",%v)`, col.Key(), rhv.Value())
		ctx.Put(col, ctx, rhv)
	case nil:
		// Special statements
		name := strings.ToLower(col.Name)
		switch {
		case strings.HasPrefix(name, "names ") || strings.HasPrefix(name, "character set"):
			// http://dev.mysql.com/doc/refman/5.7/en/charset-connection.html
			// hm, no idea what to do
			/*
				SET character_set_client = charset_name;
				SET character_set_results = charset_name;
				SET character_set_connection = charset_name;
			*/
		}
	default:
		u.Errorf("SET command only accepts binary nodes but got type:  %#v", arg)
		return fmt.Errorf("Un recognized command %T", arg)
	}
	return nil
}
예제 #4
0
func joinValue(ctx *Context, node expr.Node, msg datasource.Message, cols map[string]*expr.Column) (string, bool) {

	if msg == nil {
		u.Warnf("got nil message?")
	}
	//u.Infof("got message: %T  %#v", msg, cols)
	switch mt := msg.(type) {
	case *datasource.SqlDriverMessage:
		msgReader := datasource.NewValueContextWrapper(mt, cols)
		joinVal, ok := vm.Eval(msgReader, node)
		//u.Debugf("msg: %#v", msgReader)
		//u.Debugf("evaluating: ok?%v T:%T result=%v node '%v'", ok, joinVal, joinVal.ToString(), node.String())
		if !ok {
			u.Errorf("could not evaluate: %T %#v   %v", joinVal, joinVal, msg)
			return "", false
		}
		switch val := joinVal.(type) {
		case value.StringValue:
			return val.Val(), true
		default:
			u.Warnf("unknown type? %T", joinVal)
		}
	default:
		if msgReader, ok := msg.Body().(expr.ContextReader); ok {
			joinVal, ok := vm.Eval(msgReader, node)
			//u.Debugf("msg: %#v", msgReader)
			//u.Infof("evaluating: ok?%v T:%T result=%v node expr:%v", ok, joinVal, joinVal.ToString(), node.StringAST())
			if !ok {
				u.Errorf("could not evaluate: %v", msg)
				return "", false
			}
			switch val := joinVal.(type) {
			case value.StringValue:
				return val.Val(), true
			default:
				u.Warnf("unknown type? %T", joinVal)
			}
		} else {
			u.Errorf("could not convert to message reader: %T", msg.Body())
		}
	}

	return "", false
}
예제 #5
0
func (m *Upsert) updateValues(ctx *expr.Context) (int64, error) {

	select {
	case <-m.SigChan():
		return 0, nil
	default:
		// fall through
	}

	valmap := make(map[string]driver.Value, len(m.update.Values))
	for key, valcol := range m.update.Values {
		//u.Debugf("key:%v  val:%v", key, valcol)

		// TODO: #13  Need a way of expressing which layer (here, db) this expr should run in?
		//  - ie, run in backend datasource?   or here?  translate the expr to native language
		if valcol.Expr != nil {
			exprVal, ok := vm.Eval(nil, valcol.Expr)
			if !ok {
				u.Errorf("Could not evaluate: %s", valcol.Expr)
				return 0, fmt.Errorf("Could not evaluate expression: %v", valcol.Expr)
			}
			valmap[key] = exprVal.Value()
		} else {
			u.Debugf("%T  %v", valcol.Value.Value(), valcol.Value.Value())
			valmap[key] = valcol.Value.Value()
		}
		//u.Debugf("key:%v col: %v   vals:%v", key, valcol, valmap[key])
	}

	// if our backend source supports Where-Patches, ie update multiple
	dbpatch, ok := m.db.(datasource.PatchWhere)
	if ok {
		updated, err := dbpatch.PatchWhere(ctx, m.update.Where, valmap)
		u.Infof("patch: %v %v", updated, err)
		if err != nil {
			return updated, err
		}
		return updated, nil
	}

	// TODO:   If it does not implement Where Patch then we need to do a poly fill
	//      Do we have to recognize if the Where is on a primary key?
	// - for sources/queries that can't do partial updates we need to do a read first
	//u.Infof("does not implement PatchWhere")

	// Create a key from Where
	key := datasource.KeyFromWhere(m.update.Where)
	//u.Infof("key: %v", key)
	if _, err := m.db.Put(ctx, key, valmap); err != nil {
		u.Errorf("Could not put values: %v", err)
		return 0, err
	}
	u.Debugf("returning 1")
	return 1, nil
}
예제 #6
0
func (m *JoinKey) Run() error {
	defer m.Ctx.Recover()
	defer close(m.msgOutCh)

	outCh := m.MessageOut()
	inCh := m.MessageIn()
	joinNodes := m.p.Source.Stmt.JoinNodes()

	for {

		select {
		case <-m.SigChan():
			//u.Debugf("got signal quit")
			return nil
		case msg, ok := <-inCh:
			if !ok {
				//u.Debugf("NICE, got msg shutdown")
				return nil
			}

			//u.Infof("In joinkey msg %#v", msg)
		msgTypeSwitch:
			switch mt := msg.(type) {
			case *datasource.SqlDriverMessageMap:
				vals := make([]string, len(joinNodes))
				for i, node := range joinNodes {
					joinVal, ok := vm.Eval(mt, node)
					//u.Debugf("evaluating: ok?%v T:%T result=%v node '%v'", ok, joinVal, joinVal.ToString(), node.String())
					if !ok {
						u.Errorf("could not evaluate: %T %#v   %v", joinVal, joinVal, msg)
						break msgTypeSwitch
					}
					vals[i] = joinVal.ToString()
				}
				//u.Infof("joinkey: %v row:%v", vals, mt)
				key := strings.Join(vals, string(byte(0)))
				mt.SetKeyHashed(key)
				outCh <- mt
			default:
				return fmt.Errorf("To use JoinKey must use SqlDriverMessageMap but got %T", msg)
			}

		}
	}
	return nil
}
예제 #7
0
func (m *Upsert) updateValues(ctx *Context) error {

	select {
	case <-m.SigChan():
		return nil
	default:
		// fall through
	}

	valmap := make(map[string]driver.Value, len(m.update.Values))
	for key, valcol := range m.update.Values {
		//u.Debugf("key:%v  val:%v", key, valcol)
		if valcol.Expr != nil {
			exprVal, ok := vm.Eval(nil, valcol.Expr)
			if !ok {
				u.Errorf("Could not evaluate: %s", valcol.Expr)
				return fmt.Errorf("Could not evaluate expression: %v", valcol.Expr)
			}
			valmap[key] = exprVal.Value()
		} else {
			valmap[key] = valcol.Value.Value()
		}
		//u.Debugf("key:%v col: %v   vals:%v", key, valcol, valmap[key])
	}

	if dbpatch, ok := m.db.(datasource.PatchWhere); ok {
		updated, err := dbpatch.PatchWhere(ctx, m.update.Where, valmap)
		u.Infof("patch: %v %v", updated, err)
		if err != nil {
			return err
		}
	} else {
		//u.Warnf("does not implement PatchWhere")
	}
	// Need a way to PolyFill and do scan/match?

	// Create a key from Where
	key := keyFromWhere(m.update.Where)
	//u.Infof("key: %v", key)
	if _, err := m.db.Put(ctx, key, valmap); err != nil {
		u.Errorf("Could not put values: %v", err)
		return err
	}

	return nil
}
예제 #8
0
func (m *Upsert) insertRows(ctx *expr.Context, rows [][]*expr.ValueColumn) (int64, error) {
	for i, row := range rows {
		//u.Infof("In Insert Scanner iter %#v", row)
		select {
		case <-m.SigChan():
			if i == 0 {
				return 0, nil
			}
			return int64(i) - 1, nil
		default:
			vals := make([]driver.Value, len(row))
			for x, val := range row {
				if val.Expr != nil {
					exprVal, ok := vm.Eval(nil, val.Expr)
					if !ok {
						u.Errorf("Could not evaluate: %v", val.Expr)
						return 0, fmt.Errorf("Could not evaluate expression: %v", val.Expr)
					}
					//u.Debugf("%T  %v", exprVal.Value(), exprVal.Value())
					vals[x] = exprVal.Value()
				} else {
					//u.Debugf("%T  %v", val.Value.Value(), val.Value.Value())
					vals[x] = val.Value.Value()
				}
				//u.Debugf("%d col: %v   vals:%v", x, val, vals[x])
			}

			//u.Debugf("db.Put()  db:%T   %v", m.db, vals)
			if _, err := m.db.Put(ctx, nil, vals); err != nil {
				u.Errorf("Could not put values: %v", err)
				return 0, err
			}
			// continue
		}
	}
	//u.Debugf("about to return from Insert: %v", len(rows))
	return int64(len(rows)), nil
}
예제 #9
0
// Create handler function for evaluation (ie, field selection from tuples)
func (m *Projection) projectionEvaluator(isFinal bool) MessageHandler {

	out := m.MessageOut()
	columns := m.p.Stmt.Columns
	colIndex := m.p.Stmt.ColIndexes()
	limit := m.p.Stmt.Limit
	if limit == 0 {
		limit = math.MaxInt32
	}
	colCt := len(columns)
	// If we have a projection, use that as col count
	if m.p.Proj != nil {
		colCt = len(m.p.Proj.Columns)
	}

	// if m.p.Proj == nil {
	// 	u.Warnf("What, requires Projection?  %#v", m.p)
	// }
	//u.Debugf("limit: %d   colindex: %#v", limit, colIndex)
	//u.Debugf("plan projection columns: %#v", m.p.Proj.Columns)
	//u.Debugf("columns: %#v", columns)

	rowCt := 0
	return func(ctx *plan.Context, msg schema.Message) bool {

		select {
		case <-m.SigChan():
			u.Debugf("%p closed, returning", m)
			return false
		default:
		}

		//u.Infof("got projection message: %T %#v", msg, msg.Body())
		var outMsg schema.Message
		switch mt := msg.(type) {
		case *datasource.SqlDriverMessageMap:
			// use our custom write context for example purposes
			row := make([]driver.Value, colCt)
			rdr := datasource.NewNestedContextReader([]expr.ContextReader{
				mt,
				ctx.Session,
			}, mt.Ts())
			//u.Debugf("about to project: %#v", mt)
			colCt := 0
			for i, col := range columns {
				//u.Debugf("col: idx:%v sidx: %v pidx:%v key:%v   %s", col.Index, col.SourceIndex, col.ParentIndex, col.Key(), col.Expr)

				if isFinal && col.ParentIndex < 0 {
					continue
				}

				if col.Guard != nil {
					ifColValue, ok := vm.Eval(rdr, col.Guard)
					if !ok {
						u.Errorf("Could not evaluate if:   %v", col.Guard.String())
						//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
					}
					//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
					switch ifColVal := ifColValue.(type) {
					case value.BoolValue:
						if ifColVal.Val() == false {
							//u.Debugf("Filtering out col")
							continue
						}
					}
				}
				if col.Star {
					starRow := mt.Values()
					//u.Infof("star row: %#v", starRow)
					if len(columns) > 1 {
						//   select *, myvar, 1
						newRow := make([]driver.Value, len(starRow)+len(colIndex)-1)
						for curi := 0; curi < i; curi++ {
							newRow[curi] = row[curi]
						}
						row = newRow
						for _, v := range starRow {
							colCt += 1
							//writeContext.Put(&expr.Column{As: k}, nil, value.NewValue(v))
							row[i+colCt] = v
						}
					} else {
						colCt--
						for _, v := range starRow {
							colCt += 1
							//writeContext.Put(&expr.Column{As: k}, nil, value.NewValue(v))
							//u.Infof("i:%d  colct: %v   v:%v", i, colCt, v)
							row[i+colCt] = v
						}
					}

				} else if col.Expr == nil {
					u.Warnf("wat?   nil col expr? %#v", col)
				} else {
					v, ok := vm.Eval(rdr, col.Expr)
					if !ok {
						u.Warnf("failed eval key=%v  val=%#v expr:%s   mt:%#v", col.Key(), v, col.Expr, mt)
						// for k, v := range ctx.Session.Row() {
						// 	u.Infof("%p session? %s: %v", ctx.Session, k, v.Value())
						// }

					} else if v == nil {
						//u.Debugf("%#v", col)
						//u.Debugf("evaled nil? key=%v  val=%v expr:%s", col.Key(), v, col.Expr.String())
						//writeContext.Put(col, mt, v)
						//u.Infof("mt: %T  mt %#v", mt, mt)
						row[i+colCt] = nil //v.Value()
					} else {
						//u.Debugf("evaled: key=%v  val=%v", col.Key(), v.Value())
						//writeContext.Put(col, mt, v)
						row[i+colCt] = v.Value()
					}
				}
			}
			//u.Infof("row: %#v", row)
			//u.Infof("row cols: %v", colIndex)
			outMsg = datasource.NewSqlDriverMessageMap(0, row, colIndex)

		case expr.ContextReader:
			//u.Warnf("nice, got context reader? %T", mt)
			row := make([]driver.Value, len(columns))
			//u.Debugf("about to project: %#v", mt)
			colCt := 0
			for i, col := range columns {
				//u.Debugf("col: idx:%v sidx: %v pidx:%v key:%v   %s", col.Index, col.SourceIndex, col.ParentIndex, col.Key(), col.Expr)

				if isFinal && col.ParentIndex < 0 {
					continue
				}

				if col.Guard != nil {
					ifColValue, ok := vm.Eval(mt, col.Guard)
					if !ok {
						u.Errorf("Could not evaluate if:   %v", col.Guard.String())
						//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
					}
					//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
					switch ifColVal := ifColValue.(type) {
					case value.BoolValue:
						if ifColVal.Val() == false {
							//u.Debugf("Filtering out col")
							continue
						}
					}
				}
				if col.Star {
					starRow := mt.Row()
					newRow := make([]driver.Value, len(starRow)+len(colIndex))
					for curi := 0; curi < i; curi++ {
						newRow[curi] = row[curi]
					}
					row = newRow
					for _, v := range starRow {
						colCt += 1
						//writeContext.Put(&expr.Column{As: k}, nil, value.NewValue(v))
						row[i+colCt] = v
					}
				} else if col.Expr == nil {
					u.Warnf("wat?   nil col expr? %#v", col)
				} else {
					v, ok := vm.Eval(mt, col.Expr)
					if !ok {
						//u.Warnf("failed eval key=%v  val=%#v expr:%s   mt:%#v", col.Key(), v, col.Expr, mt.Row())
					} else if v == nil {
						//u.Debugf("%#v", col)
						//u.Debugf("evaled nil? key=%v  val=%v expr:%s", col.Key(), v, col.Expr.String())
						//writeContext.Put(col, mt, v)
						//u.Infof("mt: %T  mt %#v", mt, mt)
						row[i+colCt] = nil //v.Value()
					} else {
						//u.Debugf("evaled: key=%v  val=%v", col.Key(), v.Value())
						//writeContext.Put(col, mt, v)
						row[i+colCt] = v.Value()
					}
				}
			}
			//u.Infof("row: %#v cols:%#v", row, colIndex)
			//u.Infof("row cols: %v", colIndex)
			outMsg = datasource.NewSqlDriverMessageMap(0, row, colIndex)

		default:
			u.Errorf("could not project msg:  %T", msg)
		}

		if rowCt >= limit {
			//u.Debugf("%p Projection reaching Limit!!! rowct:%v  limit:%v", m, rowCt, limit)
			out <- nil // Sending nil message is a message to downstream to shutdown
			m.Quit()   // should close rest of dag as well
			return false
		}
		rowCt++

		//u.Debugf("row:%d  completed projection for: %p %#v", rowCt, out, outMsg)
		select {
		case out <- outMsg:
			return true
		case <-m.SigChan():
			return false
		}
	}
}
예제 #10
0
// Create handler function for evaluation (ie, field selection from tuples)
func (m *Projection) projectionEvaluator() MessageHandler {
	out := m.MessageOut()
	columns := m.sql.Columns
	// if len(m.sql.From) > 1 && m.sql.From[0].Source != nil && len(m.sql.From[0].Source.Columns) > 0 {
	// 	// we have re-written this query, lets build new list of columns
	// 	columns = make(expr.Columns, 0)
	// 	for _, from := range m.sql.From {
	// 		for _, col := range from.Source.Columns {
	// 			columns = append(columns, col)
	// 		}
	// 	}
	// }
	return func(ctx *expr.Context, msg datasource.Message) bool {
		// defer func() {
		// 	if r := recover(); r != nil {
		// 		u.Errorf("crap, %v", r)
		// 	}
		// }()

		//u.Infof("got projection message: %T %#v", msg, msg.Body())
		var outMsg datasource.Message
		switch mt := msg.(type) {
		case *datasource.SqlDriverMessageMap:
			// readContext := datasource.NewContextUrlValues(uv)
			// use our custom write context for example purposes
			writeContext := datasource.NewContextSimple()
			outMsg = writeContext
			//u.Debugf("about to project: %#v", mt)
			for _, col := range columns {
				if col.ParentIndex < 0 {
					continue
				}
				//u.Debugf("col: idx:%v pidx:%v key:%v   %s", col.Index, col.ParentIndex, col.Key(), col.Expr)
				if col.Guard != nil {
					ifColValue, ok := vm.Eval(mt, col.Guard)
					if !ok {
						u.Errorf("Could not evaluate if:   %v", col.Guard.String())
						//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
					}
					//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
					switch ifColVal := ifColValue.(type) {
					case value.BoolValue:
						if ifColVal.Val() == false {
							//u.Debugf("Filtering out col")
							continue
						}
					}
				}
				if col.Star {
					for k, v := range mt.Row() {
						writeContext.Put(&expr.Column{As: k}, nil, value.NewValue(v))
					}
				} else {
					v, ok := vm.Eval(mt, col.Expr)
					if !ok {
						u.Warnf("failed eval key=%v  val=%#v expr:%s   mt:%#v", col.Key(), v, col.Expr, mt)
					} else if v == nil {
						u.Debugf("evaled: key=%v  val=%v", col.Key(), v)
						writeContext.Put(col, mt, v)
					} else {
						//u.Debugf("evaled: key=%v  val=%v", col.Key(), v.Value())
						writeContext.Put(col, mt, v)
					}
				}
			}

		case *datasource.ContextUrlValues:
			// readContext := datasource.NewContextUrlValues(uv)
			// use our custom write context for example purposes
			writeContext := datasource.NewContextSimple()
			outMsg = writeContext
			//u.Infof("about to project: colsct%v %#v", len(sql.Columns), outMsg)
			for _, col := range columns {
				//u.Debugf("col:   %#v", col)
				if col.Guard != nil {
					ifColValue, ok := vm.Eval(mt, col.Guard)
					if !ok {
						u.Errorf("Could not evaluate if:   %v", col.Guard.String())
						//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
					}
					//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
					switch ifColVal := ifColValue.(type) {
					case value.BoolValue:
						if ifColVal.Val() == false {
							//u.Debugf("Filtering out col")
							continue
						}
					}
				}
				if col.Star {
					for k, v := range mt.Row() {
						writeContext.Put(&expr.Column{As: k}, nil, v)
					}
				} else {
					//u.Debugf("tree.Root: as?%v %#v", col.As, col.Expr)
					v, ok := vm.Eval(mt, col.Expr)
					//u.Debugf("evaled: ok?%v key=%v  val=%v", ok, col.Key(), v)
					if ok {
						writeContext.Put(col, mt, v)
					}
				}

			}
		default:
			u.Errorf("could not project msg:  %T", msg)
		}

		//u.Debugf("completed projection for: %p %#v", out, outMsg)
		select {
		case out <- outMsg:
			return true
		case <-m.SigChan():
			return false
		}
	}
}
예제 #11
0
// Create handler function for evaluation (ie, field selection from tuples)
func projectionEvaluator(sql *expr.SqlSelect, task TaskRunner) MessageHandler {
	out := task.MessageOut()
	//evaluator := vm.Evaluator(where)
	return func(ctx *Context, msg datasource.Message) bool {
		defer func() {
			if r := recover(); r != nil {
				u.Errorf("crap, %v", r)
			}
		}()

		//u.Infof("got projection message: %#v", msg.Body())
		var outMsg datasource.Message
		switch mt := msg.(type) {
		case *datasource.SqlDriverMessageMap:
			// readContext := datasource.NewContextUrlValues(uv)
			// use our custom write context for example purposes
			writeContext := datasource.NewContextSimple()
			outMsg = writeContext
			//u.Infof("about to project: colsct%v %#v", len(sql.Columns), outMsg)
			for _, from := range sql.From {
				for _, col := range from.Columns {
					//u.Debugf("col:   %#v", col)
					if col.Guard != nil {
						ifColValue, ok := vm.Eval(mt, col.Guard)
						if !ok {
							u.Errorf("Could not evaluate if:   %v", col.Guard.StringAST())
							//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
						}
						//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
						switch ifColVal := ifColValue.(type) {
						case value.BoolValue:
							if ifColVal.Val() == false {
								//u.Debugf("Filtering out col")
								continue
							}
						}
					}
					if col.Star {
						for k, v := range mt.Vals {
							writeContext.Put(&expr.Column{As: k}, nil, value.NewValue(v))
						}
					} else {
						//u.Debugf("tree.Root: as?%v %v", col.As, col.Expr.String())
						v, ok := vm.Eval(mt, col.Expr)
						//u.Debugf("evaled: ok?%v key=%v  val=%v", ok, col.Key(), v)
						if ok {
							writeContext.Put(col, mt, v)
						}
					}
				}
			}

		case *datasource.ContextUrlValues:
			// readContext := datasource.NewContextUrlValues(uv)
			// use our custom write context for example purposes
			writeContext := datasource.NewContextSimple()
			outMsg = writeContext
			//u.Infof("about to project: colsct%v %#v", len(sql.Columns), outMsg)
			for _, col := range sql.Columns {
				//u.Debugf("col:   %#v", col)
				if col.Guard != nil {
					ifColValue, ok := vm.Eval(mt, col.Guard)
					if !ok {
						u.Errorf("Could not evaluate if:   %v", col.Guard.StringAST())
						//return fmt.Errorf("Could not evaluate if clause: %v", col.Guard.String())
					}
					//u.Debugf("if eval val:  %T:%v", ifColValue, ifColValue)
					switch ifColVal := ifColValue.(type) {
					case value.BoolValue:
						if ifColVal.Val() == false {
							//u.Debugf("Filtering out col")
							continue
						}
					}
				}
				if col.Star {
					for k, v := range mt.Row() {
						writeContext.Put(&expr.Column{As: k}, nil, v)
					}
				} else {
					//u.Debugf("tree.Root: as?%v %#v", col.As, col.Expr)
					v, ok := vm.Eval(mt, col.Expr)
					//u.Debugf("evaled: ok?%v key=%v  val=%v", ok, col.Key(), v)
					if ok {
						writeContext.Put(col, mt, v)
					}
				}

			}
		default:
			u.Errorf("could not project msg:  %T", msg)
		}

		//u.Debugf("completed projection for: %p %#v", out, outMsg)
		select {
		case out <- outMsg:
			return true
		case <-task.SigChan():
			return false
		}
	}
}