public Select( G.List<Exp> exps, TableExpression te, Exp where, Exp[] group, OrderByExp[] order, bool [] used, SqlExec x ) { /* There is more work to be done here, for example 2 * SUM(Total) is currently not allowed. Also if there is a GROUP BY, SELECT expressions should not be allowed to access fields not in the group list, unless thereis an enclosing aggregate function. Also maybe common sub-expression analysis, and perhaps constant folding, could be done? */ Exps = exps; TE = te; Where = where; Order = order; ColumnCount = exps.Count; var names = new string[ ColumnCount ]; var types = new DataType[ ColumnCount ]; for ( int i = 0; i < ColumnCount; i += 1 ) { names[ i ] = exps[ i ].Name; types[ i ] = exps[ i ].Type; } CI = new ColInfo( names, types ); if ( x.ParseOnly ) return; Used = Util.ToList( used ); if ( group != null ) { // Compute AggSpec and GroupSpec var alist = new G.List<AggSpec>(); for ( int i = 0; i < exps.Count; i += 1 ) { Exp e = exps[ i ]; AggOp op = e.GetAggOp(); if ( op != AggOp.None ) { AggSpec a = new AggSpec(); a.ColIx = i; a.Type = e.Type; a.Op = op; alist.Add( a ); } } AggSpec = alist.ToArray(); var glist = new G.List<GroupSpec>(); for ( int i=0; i < group.Length; i += 1 ) { GroupSpec g = new GroupSpec(); g.ColIx = Exps.Count; g.Type = group[ i ].Type; Exps.Add( group[ i ] ); glist.Add( g ); } GroupSpec = glist.ToArray(); } if ( Order != null ) { var sortSpec = new SortSpec[ Order.Length ]; for ( int i = 0; i < Order.Length; i += 1 ) { // Quite complicated as ORDER BY can use aliases or expressions. Exp e = Order[ i ].E; sortSpec[ i ].Desc = Order[ i ].Desc; int cix = -1; if ( e is ExpName ) { string alias = ((ExpName)e).ColName; for ( int j = 0; j < CI.Count; j += 1 ) { if ( CI.Name[j] == alias ) { e = Exps[ j ]; cix = j; break; } } } if ( cix < 0 ) { cix = Exps.Count; Exps.Add( e ); e.Bind( x ); } sortSpec[ i ].Type = e.Type; sortSpec[ i ].ColIx = cix; } SortSpec = sortSpec; } Dvs = Util.GetDVList( Exps.ToArray() ); if ( Where != null ) WhereD = Where.GetDB(); Ids = Where == null ? null : Where.GetIdSet( TE ); if ( Ids != null ) Ids = new IdCopy( Ids ); // Need to take a copy of the id values if an index is used. }
public ExpAgg( AggOp op, G.List<Exp> arg, SqlExec e ) { Op = op; if ( arg.Count != 1 ) e.Error( Op + " takes one parameter" ); E = arg[0]; }
public Select( G.List<Exp> exps, TableExpression te, Exp where, Exp[] group, OrderByExp[] order, bool [] used, SqlExec x ) { Exps = exps; TE = te; Where = where; Order = order; Used = used; ColumnCount = exps.Count; var names = new string[ ColumnCount ]; var types = new DataType[ ColumnCount ]; for ( int i = 0; i < ColumnCount; i += 1 ) { names[i] = exps[i].Name; types[i] = exps[i].Type; } Cols = new ColInfo( names, types ); if ( x.ParseOnly ) return; if ( group != null ) { // Compute AggSpec and GroupSpec var alist = new G.List<AggSpec>(); for ( int i = 0; i < exps.Count; i += 1 ) { Exp e = exps[i]; AggOp op = e.GetAggOp(); if ( op != AggOp.None ) { AggSpec a = new AggSpec(); a.ColIx = i; a.Type = e.Type; a.Op = op; alist.Add( a ); } } AggSpec = alist.ToArray(); var glist = new G.List<GroupSpec>(); for ( int i=0; i < group.Length; i += 1 ) { GroupSpec g = new GroupSpec(); g.ColIx = Exps.Count; // Note: we could look in Exps to see if it is already there rather than adding an extra Exp. g.Type = group[ i ].Type; Exps.Add( group[ i ] ); glist.Add( g ); } GroupSpec = glist.ToArray(); } if ( Order != null ) { var sortSpec = new SortSpec[ Order.Length ]; for ( int i = 0; i < Order.Length; i += 1 ) { // Quite complicated as ORDER BY can use aliases or expressions. Exp e = Order[i].E; sortSpec[ i ].Desc = Order[i].Desc; bool found = false; if ( e is ExpName ) { string alias = ((ExpName)e).ColName; for ( int j = 0; j < Cols.Count; j += 1 ) { if ( Cols.Names[j] == alias ) { e = Exps[ j ]; found = true; break; } } } int cix = Exps.Count; Exps.Add( e ); if ( !found ) e.Bind( x ); sortSpec[ i ].Type = e.Type; sortSpec[ i ].ColIx = cix; } SortSpec = sortSpec; } }