Before I give my thoughts on this I do want to just put into writing an important note that I think will help frame the conversation.
None of the Streaming classes require the use of streaming expressions. Streaming Expressions is just a way to turn a human readable expression into valid streaming constructs. You can, if you want, just create instances of streaming classes without ever thinking about expressions. The SQL api (in SQLHandler.java) currently works this way.
That said, I do feel that expressions are the easiest and clearest way to interact with Streams. They provide a very concrete yet expressive way to turn a streaming query into objects that do all the actual work. And they are bi-directional in that you can turn a set of stream objects into an expression as easily as you can turn an expression into a set of stream objects. From a user's perspective I find expressions easier to understand than even standard Solr queries, particularly when performing things like aggregations, top, and joins. I can look at an expression and know exactly what I should expect to receive as a result.
I'm not adverse to the your suggestion that we create a pipeline of SQL Statement -> Expression -> Stream object. That said, I don't think it would be good idea (from a performance perspective) to create a streaming expression in string format. Ie, "SELECT fieldA FROM collection1 WHERE fieldB = 1" -> search(collection1, fl="fieldA", q="fieldB:1"). I would instead suggest that we turn a SQL statement into a StreamExpression object. This would remove the need to reparse a string just to end up with a StreamExpression object. For example, the above SQL statement could be turned into a StreamExpression with the code
StreamExpression expression = new StreamExpression("search")
which can then be turned into a Stream with
TupleStream stream = streamFactory.constructStream(expression);
Thinking about this wrt the string representation of an expression, we really end up with a rather clear pipeline of [SQL Statement | String Expression] -> StreamExpression -> TupleStream. This pipeline makes it very clear that whatever your input format is you only need to convert it into a StreamExpression object and that's it - all the other work of creating a stream from a StreamExpression object is already done.
I think this is the correct approach.