override internal void FinalPass() { _ds = OwnerReport.DataSetsDefn[this._DataSetName]; if (_ds == null) OwnerReport.rl.LogError(8, "DataSetReference refers to unknown data set '" + _DataSetName + "'"); else { _vField = _ds.Fields[_ValueField]; if (_vField == null) OwnerReport.rl.LogError(8, "ValueField refers to unknown field '" + _ValueField + "'"); else { if (_LabelField == null) _lField = _vField; else { _lField = _ds.Fields[_LabelField]; if (_lField == null) OwnerReport.rl.LogError(8, "LabelField refers to unknown field '" + _LabelField + "'"); } } } return; }
DataRegion _ParentDataRegion; // when DataRegions are nested; the nested regions have the parent set internal DataRegion(ReportDefn r, ReportLink p, XmlNode xNode):base(r,p,xNode) { _KeepTogether=false; _NoRows=null; _DataSetName=null; _DataSetDefn=null; _PageBreakAtStart=false; _PageBreakAtEnd=false; _Filters=null; }
IDictionary _Items; // list of report items internal DataSetsDefn(ReportDefn r, ReportLink p, XmlNode xNode) : base(r, p) { if (xNode.ChildNodes.Count < 10) _Items = new ListDictionary(); // Hashtable is overkill for small lists else _Items = new Hashtable(xNode.ChildNodes.Count); // Loop thru all the child nodes foreach(XmlNode xNodeLoop in xNode.ChildNodes) { if (xNodeLoop.NodeType != XmlNodeType.Element) continue; if (xNodeLoop.Name == "DataSet") { DataSetDefn ds = new DataSetDefn(r, this, xNodeLoop); if (ds != null && ds.Name != null) _Items.Add(ds.Name.Nm, ds); } } }
Report _rpt; // the runtime report #endregion Fields #region Constructors internal DataSet(Report rpt, DataSetDefn dsd) { _rpt = rpt; _dsd = dsd; }
DataSetDefn _dsd; // the true definition of the DataSet internal DataSet(Report rpt, DataSetDefn dsd) { _rpt = rpt; _dsd = dsd; }
// return an IEnumerable that represents the scope of the data protected RowEnumerable GetDataScope(Report rpt, Row row, out bool bSave) { bSave = true; RowEnumerable re = null; if (this._Scope != null) { Type t = this._Scope.GetType(); //150208AJM GJL Trying - And Succeeding!!! to get data from chart if (t == typeof(Chart)) { Chart c = (Chart)this._Scope; this._Scope = c.ChartMatrix; t = this._Scope.GetType(); } if (t == typeof(Grouping)) { bSave = false; Grouping g = (Grouping)(this._Scope); if (g.InMatrix) { Rows rows = g.GetRows(rpt); if (rows == null) { return(null); } re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, _LevelCheck); } else { if (row == null || row.R.CurrentGroups == null) // currentGroups can be null when reference Textbox in header/footer that has a scoped aggr function reference (TODO: this is a problem!) { return(null); } GroupEntry ge = row.R.CurrentGroups[g.GetIndex(rpt)]; re = new RowEnumerable(ge.StartRow, ge.EndRow, row.R.Data, _LevelCheck); } } else if (t == typeof(Matrix)) { bSave = false; Matrix m = (Matrix)(this._Scope); Rows mData = m.GetMyData(rpt); re = new RowEnumerable(0, mData.Data.Count - 1, mData.Data, false); } else if (t == typeof(string)) { // happens on page header/footer scope if (row != null) { re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false); } bSave = false; } else if (row != null) { re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false); } else { DataSetDefn ds = this._Scope as DataSetDefn; if (ds != null && ds.Query != null) { Rows rows = ds.Query.GetMyData(rpt); if (rows != null) { re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, false); } } } } else if (row != null) { re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false); } return(re); }
// Handle parsing of function in final pass override internal void FinalPass() { base.FinalPass(); // DataRegions aren't allowed in PageHeader or PageFooter; if (this.InPageHeaderOrFooter()) OwnerReport.rl.LogError(8, String.Format("The DataRegion '{0}' is not allowed in a PageHeader or PageFooter", this.Name == null? "unknown": Name.Nm) ); ResolveNestedDataRegions(); if (_ParentDataRegion != null) // when nested we use the dataset of the parent { _DataSetDefn = _ParentDataRegion.DataSetDefn; } else if (_DataSetName != null) { if (OwnerReport.DataSetsDefn != null) _DataSetDefn = (DataSetDefn) OwnerReport.DataSetsDefn.Items[_DataSetName]; if (_DataSetDefn == null) { OwnerReport.rl.LogError(8, String.Format("DataSetName '{0}' not specified in DataSets list.", _DataSetName)); } } else { // No name but maybe we can default to a single Dataset if (_DataSetDefn == null && OwnerReport.DataSetsDefn != null && OwnerReport.DataSetsDefn.Items.Count == 1) { foreach (DataSetDefn d in OwnerReport.DataSetsDefn.Items.Values) { _DataSetDefn = d; break; // since there is only 1 this will obtain it } } if (_DataSetDefn == null) OwnerReport.rl.LogError(8, string.Format("{0} must specify a DataSetName.",this.Name == null? "DataRegions": this.Name.Nm)); } if (_NoRows != null) _NoRows.FinalPass(); if (_Filters != null) _Filters.FinalPass(); return; }
// Handle parsing of function in final pass override internal void FinalPass() { base.FinalPass(); if (this is Table) { // Grids don't have any data responsibilities Table t = this as Table; if (t.IsGrid) { return; } } // DataRegions aren't allowed in PageHeader or PageFooter; if (this.InPageHeaderOrFooter()) { OwnerReport.rl.LogError(8, String.Format("The DataRegion '{0}' is not allowed in a PageHeader or PageFooter", this.Name == null? "unknown": Name.Nm)); } ResolveNestedDataRegions(); if (_ParentDataRegion != null) // when nested we use the dataset of the parent { _DataSetDefn = _ParentDataRegion.DataSetDefn; } else if (_DataSetName != null) { if (OwnerReport.DataSetsDefn != null) { _DataSetDefn = (DataSetDefn)OwnerReport.DataSetsDefn.Items[_DataSetName]; } if (_DataSetDefn == null) { OwnerReport.rl.LogError(8, String.Format("DataSetName '{0}' not specified in DataSets list.", _DataSetName)); } } else { // No name but maybe we can default to a single Dataset if (_DataSetDefn == null && OwnerReport.DataSetsDefn != null && OwnerReport.DataSetsDefn.Items.Count == 1) { foreach (DataSetDefn d in OwnerReport.DataSetsDefn.Items.Values) { _DataSetDefn = d; break; // since there is only 1 this will obtain it } } if (_DataSetDefn == null) { OwnerReport.rl.LogError(8, string.Format("{0} must specify a DataSetName.", this.Name == null? "DataRegions": this.Name.Nm)); } } if (_NoRows != null) { _NoRows.FinalPass(); } if (_Filters != null) { _Filters.FinalPass(); } return; }
override internal void FinalPass() { // optimization: avoid expression overhead if this isn't really an expression if (_Source == null) { _Expr = new Constant(""); return; } else if (_Source == "" || // empty expression _Source[0] != '=') // if 1st char not '=' { _Expr = new Constant(_Source); // this is a constant value return; } Parser p = new Parser(OwnerReport.DataCache); // find the fields that are part of the DataRegion (if there is one) IDictionary fields = null; ReportLink dr = Parent; Grouping grp = null; // remember if in a table group or detail group or list group Matrix m = null; ReportLink phpf = null; while (dr != null) { if (dr is Grouping) { p.NoAggregateFunctions = true; } else if (dr is TableGroup) { grp = ((TableGroup)dr).Grouping; } else if (dr is Matrix) { m = (Matrix)dr; // if matrix we need to pass special break; } else if (dr is Details) { grp = ((Details)dr).Grouping; } else if (dr is List) { grp = ((List)dr).Grouping; break; } else if (dr is PageHeader || dr is PageFooter) { phpf = dr; } else if (dr is DataRegion || dr is DataSetDefn) { break; } dr = dr.Parent; } if (dr != null) { if (dr is DataSetDefn) { DataSetDefn d = (DataSetDefn)dr; if (d.Fields != null) { fields = d.Fields.Items; } } else // must be a DataRegion { DataRegion d = (DataRegion)dr; if (d.DataSetDefn != null && d.DataSetDefn.Fields != null) { fields = d.DataSetDefn.Fields.Items; } } } NameLookup lu = new NameLookup(fields, OwnerReport.LUReportParameters, OwnerReport.LUReportItems, OwnerReport.LUGlobals, OwnerReport.LUUser, OwnerReport.LUAggrScope, grp, m, OwnerReport.CodeModules, OwnerReport.Classes, OwnerReport.DataSetsDefn, OwnerReport.CodeType); if (phpf != null) { // Non-null when expression is in PageHeader or PageFooter; // Expression name needed for dynamic lookup of ReportItems on a page. lu.PageFooterHeader = phpf; lu.ExpressionName = _UniqueName = "xn_" + Interlocked.Increment(ref Parser.Counter).ToString(); } try { _Expr = p.Parse(lu, _Source); } catch (Exception e) { _Expr = new ConstantError(e.Message); // Invalid expression OwnerReport.rl.LogError(8, ErrorText(e.Message)); } // Optimize removing any expression that always result in a constant try { _Expr = _Expr.ConstantOptimization(); } catch (Exception ex) { OwnerReport.rl.LogError(4, "Expression:" + _Source + "\r\nConstant Optimization exception:\r\n" + ex.Message + "\r\nStack trace:\r\n" + ex.StackTrace); } _Type = _Expr.GetTypeCode(); return; }
internal TypeCode DoParse(Report rpt) { // optimization: avoid expression overhead if this isn't really an expression if (_Source == null) { _Expr = new Constant(""); return(_Expr.GetTypeCode()); } else if (_Source == string.Empty || // empty expression _Source[0] != '=') // if 1st char not '=' { _Expr = new Constant(_Source); // this is a constant value return(_Expr.GetTypeCode()); } Parser p = new Parser(new System.Collections.Generic.List <ICacheData>()); // find the fields that are part of the DataRegion (if there is one) IDictionary fields = null; ReportLink dr = _rl.Parent; Grouping grp = null; // remember if in a table group or detail group or list group Matrix m = null; while (dr != null) { if (dr is Grouping) { p.NoAggregateFunctions = true; } else if (dr is TableGroup) { grp = ((TableGroup)dr).Grouping; } else if (dr is Matrix) { m = (Matrix)dr; // if matrix we need to pass special break; } else if (dr is Details) { grp = ((Details)dr).Grouping; } else if (dr is List) { grp = ((List)dr).Grouping; break; } else if (dr is DataRegion || dr is DataSetDefn) { break; } dr = dr.Parent; } if (dr != null) { if (dr is DataSetDefn) { DataSetDefn d = (DataSetDefn)dr; if (d.Fields != null) { fields = d.Fields.Items; } } else // must be a DataRegion { DataRegion d = (DataRegion)dr; if (d.DataSetDefn != null && d.DataSetDefn.Fields != null) { fields = d.DataSetDefn.Fields.Items; } } } NameLookup lu = new NameLookup(fields, rpt.ReportDefinition.LUReportParameters, rpt.ReportDefinition.LUReportItems, rpt.ReportDefinition.LUGlobals, rpt.ReportDefinition.LUUser, rpt.ReportDefinition.LUAggrScope, grp, m, rpt.ReportDefinition.CodeModules, rpt.ReportDefinition.Classes, rpt.ReportDefinition.DataSetsDefn, rpt.ReportDefinition.CodeType); try { _Expr = p.Parse(lu, _Source); } catch (Exception e) { _Expr = new ConstantError(e.Message); // Invalid expression rpt.rl.LogError(8, ErrorText(e.Message)); } // Optimize removing any expression that always result in a constant try { _Expr = _Expr.ConstantOptimization(); } catch (Exception ex) { rpt.rl.LogError(4, "Expression:" + _Source + "\r\nConstant Optimization exception:\r\n" + ex.Message + "\r\nStack trace:\r\n" + ex.StackTrace); } return(_Expr.GetTypeCode()); }
// return an IEnumerable that represents the scope of the data protected RowEnumerable GetDataScope(Report rpt, Row row, out bool bSave) { bSave = true; RowEnumerable re = null; if (this._Scope != null) { Type t = this._Scope.GetType(); if (t == typeof(Grouping)) { bSave = false; Grouping g = (Grouping)(this._Scope); if (g.InMatrix) { Rows rows = g.GetRows(rpt); if (rows == null) { return(null); } re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, _LevelCheck); } else { if (row == null) { return(null); } GroupEntry ge = row.R.CurrentGroups[g.GetIndex(rpt)]; re = new RowEnumerable(ge.StartRow, ge.EndRow, row.R.Data, _LevelCheck); } } else if (t == typeof(Matrix)) { bSave = false; Matrix m = (Matrix)(this._Scope); Rows mData = m.GetMyData(rpt); re = new RowEnumerable(0, mData.Data.Count - 1, mData.Data, false); } else if (t == typeof(string)) { // happens on page header/footer scope if (row != null) { re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false); } bSave = false; } else if (row != null) { re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false); } else { DataSetDefn ds = this._Scope as DataSetDefn; if (ds != null && ds.Query != null) { Rows rows = ds.Query.GetMyData(rpt); if (rows != null) { re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, false); } } } } else if (row != null) { re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false); } return(re); }
// FuncIDent: IDENTIFIER ( [Expr] [, Expr]*) | IDENTIFIER private bool MatchFuncIDent(out IExpr result) { IExpr e; string fullname; // will hold the full name string method; // will hold method name or second part of name string firstPart; // will hold the collection name string thirdPart; // will hold third part of name bool bOnePart; // simple name: no ! or . in name result = null; if (curToken.Type != TokenTypes.IDENTIFIER) return false; // Disentangle method calls from collection references method = fullname = curToken.Value; curToken = tokens.Extract(); // Break the name into parts char[] breakChars = new char[] {'!', '.'}; int posBreak = method.IndexOfAny(breakChars); if (posBreak > 0) { bOnePart = false; firstPart = method.Substring(0, posBreak); method = method.Substring(posBreak+1); // rest of expression } else { bOnePart = true; firstPart = method; } posBreak = method.IndexOf('.'); if (posBreak > 0) { thirdPart = method.Substring(posBreak + 1); // rest of expression method = method.Substring(0, posBreak); } else { thirdPart = null; } if (curToken.Type != TokenTypes.LPAREN) switch (firstPart) { case "Fields": Field f = null; if (inAggregateDataSet != null) { f = inAggregateDataSet.Fields == null ? null : inAggregateDataSet.Fields[method]; if (f == null) throw new ParserException(string.Format(Strings.Parser_ErrorP_FieldNotInDataSet, method, inAggregateDataSet.Name.Nm)); } else { f = idLookup.LookupField(method); if (f == null) { throw new ParserException(string.Format(Strings.Parser_ErrorP_FieldNotFound, method)); } } if (thirdPart == null || thirdPart == "Value") { result = new FunctionField(f); } else if (thirdPart == "IsMissing") { result = new FunctionFieldIsMissing(f); } else throw new ParserException(string.Format(Strings.Parser_ErrorP_FieldSupportsValueAndIsMissing, method)); return true; case "Parameters": // see ResolveParametersMethod for resolution of MultiValue parameter function reference ReportParameter p = idLookup.LookupParameter(method); if (p == null) throw new ParserException(string.Format(Strings.Parser_ErrorP_ParameterNotFound, method)); int ci = thirdPart == null? -1: thirdPart.IndexOf(".Count"); if (ci > 0) thirdPart = thirdPart.Substring(0, ci); FunctionReportParameter r; if (thirdPart == null || thirdPart == "Value") r = new FunctionReportParameter(p); else if (thirdPart == "Label") r = new FunctionReportParameterLabel(p); else throw new ParserException(string.Format(Strings.Parser_ErrorP_ParameterSupportsValueAndLabel, method)); if (ci > 0) r.SetParameterMethod("Count", null); result = r; return true; case "ReportItems": Textbox t = idLookup.LookupReportItem(method); if (t == null) throw new ParserException(string.Format(Strings.Parser_ErrorP_ItemNotFound, method)); if (thirdPart != null && thirdPart != "Value") throw new ParserException(string.Format(Strings.Parser_ErrorP_ItemSupportsValue, method)); result = new FunctionTextbox(t, idLookup.ExpressionName); return true; case "Globals": e = idLookup.LookupGlobal(method); if (e == null) throw new ParserException(string.Format(Strings.Parser_ErrorP_GlobalsNotFound, method)); result = e; return true; case "User": e = idLookup.LookupUser(method); if (e == null) throw new ParserException(string.Format(Strings.Parser_ErrorP_UserVarNotFound, method)); result = e; return true; case "Recursive": // Only valid for some aggregate functions result = new IdentifierKey(IdentifierKeyEnum.Recursive); return true; case "Simple": // Only valid for some aggregate functions result = new IdentifierKey(IdentifierKeyEnum.Simple); return true; default: if (!bOnePart) throw new ParserException(string.Format(Strings.Parser_ErrorP_UnknownIdentifer, fullname)); switch (method.ToLower()) // lexer should probably mark these { case "true": case "false": result = new ConstantBoolean(method.ToLower()); break; default: // usually this is enum that will be used in an aggregate result = new Identifier(method); break; } return true; } // We've got an function reference curToken = tokens.Extract(); // get rid of '(' // Got a function now obtain the arguments int argCount=0; bool isAggregate = IsAggregate(method, bOnePart); if (_NoAggregate && isAggregate) throw new ParserException(string.Format(Strings.Parser_ErrorP_AggregateCannotUsedWithinGrouping, method)); if (_InAggregate && isAggregate) throw new ParserException(string.Format(Strings.Parser_ErrorP_AggregateCannotNestedInAnotherAggregate, method)); _InAggregate = isAggregate; if (_InAggregate) { int level = 0; bool nextScope = false; Token scopeToken = null; foreach(Token tok in tokens) { if(nextScope) { scopeToken = tok; break; } if(level == 0 && tok.Type == TokenTypes.COMMA) { nextScope = true; continue; } if (tok.Type == TokenTypes.RPAREN) level--; if (tok.Type == TokenTypes.LPAREN) level++; } if (scopeToken != null) { if (scopeToken.Type != TokenTypes.QUOTE) throw new ParserException(string.Format(Strings.Parser_ErrorP_ScopeMustConstant, scopeToken.Value)); inAggregateDataSet = this.idLookup.ScopeDataSet(scopeToken.Value); if (inAggregateDataSet == null) throw new ParserException(string.Format(Strings.Parser_ErrorP_ScopeNotKnownDataSet, scopeToken.Value)); } } List<IExpr> largs = new List<IExpr>(); while(true) { if (curToken.Type == TokenTypes.RPAREN) { // We've got our function curToken = tokens.Extract(); break; } if (argCount == 0) { // don't need to do anything } else if (curToken.Type == TokenTypes.COMMA) { curToken = tokens.Extract(); } else throw new ParserException(Strings.Parser_ErrorP_Invalid_function_arguments + GetLocationInfoWithValue(curToken)); MatchExprAndOr(out e); if (e == null) throw new ParserException(Strings.Parser_ErrorP_ExpectingComma + GetLocationInfoWithValue(curToken)); largs.Add(e); argCount++; } if (_InAggregate) { inAggregateDataSet = null; _InAggregate = false; } IExpr[] args = largs.ToArray(); object scope; bool bSimple; if (!bOnePart) { result = (firstPart == "Parameters")? ResolveParametersMethod(method, thirdPart, args): ResolveMethodCall(fullname, args); // throw exception when fails } else switch(method.ToLower()) { case "iif": if (args.Length != 3) throw new ParserException(Strings.Parser_ErrorP_iff_function_requires_3_arguments + GetLocationInfo(curToken)); // We allow any type for the first argument; it will get converted to boolean at runtime // if (args[0].GetTypeCode() != TypeCode.Boolean) // throw new ParserException("First argument to iif function must be boolean." + GetLocationInfo(curToken)); result = new FunctionIif(args[0], args[1], args[2]); break; case "choose": if (args.Length <= 2) throw new ParserException(Strings.Parser_ErrorP_ChooseRequires2Arguments + GetLocationInfo(curToken)); switch (args[0].GetTypeCode()) { case TypeCode.Double: case TypeCode.Single: case TypeCode.Int32: case TypeCode.Decimal: case TypeCode.Int16: case TypeCode.Int64: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: break; default: throw new ParserException(Strings.Parser_ErrorP_ChooseFirstArgumentMustNumeric + GetLocationInfo(curToken)); } result = new FunctionChoose(args); break; case "switch": if (args.Length <= 2) throw new ParserException(Strings.Parser_ErrorP_SwitchRequires2Arguments + GetLocationInfo(curToken)); if (args.Length % 2 != 0) throw new ParserException(Strings.Parser_ErrorP_SwitchMustEvenArguments + GetLocationInfo(curToken)); for (int i=0; i < args.Length; i = i+2) { if (args[i].GetTypeCode() != TypeCode.Boolean) throw new ParserException(Strings.Parser_ErrorP_SwitchMustBoolean + GetLocationInfo(curToken)); } result = new FunctionSwitch(args); break; case "format": if (args.Length > 2 || args.Length < 1) throw new ParserException(Strings.Parser_ErrorP_FormatRequires2Arguments + GetLocationInfo(curToken)); if (args.Length == 1) { result = new FunctionFormat(args[0], new ConstantString("")); } else { if (args[1].GetTypeCode() != TypeCode.String) throw new ParserException(Strings.Parser_ErrorP_SecondMustString + GetLocationInfo(curToken)); result = new FunctionFormat(args[0], args[1]); } break; case "fields": if (args.Length != 1) throw new ParserException(Strings.Parser_ErrorP_FieldsRequires1Argument + GetLocationInfo(curToken)); result = new FunctionFieldCollection(idLookup.Fields, args[0]); if (curToken.Type == TokenTypes.DOT) { // user placed "." TODO: generalize this code curToken = tokens.Extract(); // skip past dot operator if (curToken.Type == TokenTypes.IDENTIFIER && curToken.Value.ToLowerInvariant() == "value") curToken = tokens.Extract(); // only support "value" property for now else throw new ParserException(string.Format(Strings.Parser_ErrorP_UnknownProperty, curToken.Value, "Fields") + GetLocationInfo(curToken)); } break; case "parameters": if (args.Length != 1) throw new ParserException(Strings.Parser_ErrorP_ParametersRequires1Argument + GetLocationInfo(curToken)); result = new FunctionParameterCollection(idLookup.Parameters, args[0]); if (curToken.Type == TokenTypes.DOT) { // user placed "." curToken = tokens.Extract(); // skip past dot operator if (curToken.Type == TokenTypes.IDENTIFIER && curToken.Value.ToLowerInvariant() == "value") curToken = tokens.Extract(); // only support "value" property for now else throw new ParserException((string.Format(Strings.Parser_ErrorP_UnknownProperty, curToken.Value, "Parameters") + GetLocationInfo(curToken))); } break; case "reportitems": if (args.Length != 1) throw new ParserException(Strings.Parser_ErrorP_ReportItemsRequires1Argument + GetLocationInfo(curToken)); result = new FunctionReportItemCollection(idLookup.ReportItems, args[0]); if (curToken.Type == TokenTypes.DOT) { // user placed "." curToken = tokens.Extract(); // skip past dot operator if (curToken.Type == TokenTypes.IDENTIFIER && curToken.Value.ToLowerInvariant() == "value") curToken = tokens.Extract(); // only support "value" property for now else throw new ParserException((string.Format(Strings.Parser_ErrorP_UnknownProperty, curToken.Value, "ReportItems") + GetLocationInfo(curToken))); } break; case "globals": if (args.Length != 1) throw new ParserException(Strings.Parser_ErrorP_GlobalsRequires1Argument + GetLocationInfo(curToken)); result = new FunctionGlobalCollection(idLookup.Globals, args[0]); break; case "user": if (args.Length != 1) throw new ParserException(Strings.Parser_ErrorP_UserRequires1Argument + GetLocationInfo(curToken)); result = new FunctionUserCollection(idLookup.User, args[0]); break; case "sum": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrSum aggrFS = new FunctionAggrSum(_DataCache, args[0], scope); aggrFS.LevelCheck = bSimple; result = aggrFS; break; case "avg": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrAvg aggrFA = new FunctionAggrAvg(_DataCache, args[0], scope); aggrFA.LevelCheck = bSimple; result = aggrFA; break; case "min": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrMin aggrFMin = new FunctionAggrMin(_DataCache, args[0], scope); aggrFMin.LevelCheck = bSimple; result = aggrFMin; break; case "max": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrMax aggrFMax = new FunctionAggrMax(_DataCache, args[0], scope); aggrFMax.LevelCheck = bSimple; result = aggrFMax; break; case "first": scope = ResolveAggrScope(args, 2, out bSimple); result = new FunctionAggrFirst(_DataCache, args[0], scope); break; case "last": scope = ResolveAggrScope(args, 2, out bSimple); result = new FunctionAggrLast(_DataCache, args[0], scope); break; case "next": scope = ResolveAggrScope(args, 2, out bSimple); result = new FunctionAggrNext(_DataCache, args[0], scope); break; case "previous": scope = ResolveAggrScope(args, 2, out bSimple); result = new FunctionAggrPrevious(_DataCache, args[0], scope); break; case "level": scope = ResolveAggrScope(args, 1, out bSimple); result = new FunctionAggrLevel(scope); break; case "aggregate": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrArray aggr = new FunctionAggrArray(_DataCache, args[0], scope); aggr.LevelCheck = bSimple; result = aggr; break; case "count": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrCount aggrFC = new FunctionAggrCount(_DataCache, args[0], scope); aggrFC.LevelCheck = bSimple; result = aggrFC; break; case "countrows": scope = ResolveAggrScope(args, 1, out bSimple); FunctionAggrCountRows aggrFCR = new FunctionAggrCountRows(scope); aggrFCR.LevelCheck = bSimple; result = aggrFCR; break; case "countdistinct": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrCountDistinct aggrFCD = new FunctionAggrCountDistinct(_DataCache, args[0], scope); aggrFCD.LevelCheck = bSimple; result = aggrFCD; break; case "rownumber": scope = ResolveAggrScope(args, 1, out bSimple); IExpr texpr = new ConstantDouble("0"); result = new FunctionAggrRvCount(_DataCache, texpr, scope); break; case "runningvalue": if (args.Length < 2 || args.Length > 3) throw new ParserException(Strings.Parser_ErrorP_RunningValue_takes_2_or_3_arguments + GetLocationInfo(curToken)); string aggrFunc = args[1].EvaluateString(null, null); if (aggrFunc == null) throw new ParserException(Strings.Parser_ErrorP_RunningValueArgumentInvalid + GetLocationInfo(curToken)); scope = ResolveAggrScope(args, 3, out bSimple); switch(aggrFunc.ToLower()) { case "sum": result = new FunctionAggrRvSum(_DataCache, args[0], scope); break; case "avg": result = new FunctionAggrRvAvg(_DataCache, args[0], scope); break; case "count": result = new FunctionAggrRvCount(_DataCache, args[0], scope); break; case "max": result = new FunctionAggrRvMax(_DataCache, args[0], scope); break; case "min": result = new FunctionAggrRvMin(_DataCache, args[0], scope); break; case "stdev": result = new FunctionAggrRvStdev(_DataCache, args[0], scope); break; case "stdevp": result = new FunctionAggrRvStdevp(_DataCache, args[0], scope); break; case "var": result = new FunctionAggrRvVar(_DataCache, args[0], scope); break; case "varp": result = new FunctionAggrRvVarp(_DataCache, args[0], scope); break; default: throw new ParserException(string.Format(Strings.Parser_ErrorP_RunningValueNotSupported, aggrFunc) + GetLocationInfo(curToken)); } break; case "stdev": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrStdev aggrSDev = new FunctionAggrStdev(_DataCache, args[0], scope); aggrSDev.LevelCheck = bSimple; result = aggrSDev; break; case "stdevp": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrStdevp aggrSDevP = new FunctionAggrStdevp(_DataCache, args[0], scope); aggrSDevP.LevelCheck = bSimple; result = aggrSDevP; break; case "var": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrVar aggrVar = new FunctionAggrVar(_DataCache, args[0], scope); aggrVar.LevelCheck = bSimple; result = aggrVar; break; case "varp": scope = ResolveAggrScope(args, 2, out bSimple); FunctionAggrVarp aggrVarP = new FunctionAggrVarp(_DataCache, args[0], scope); aggrVarP.LevelCheck = bSimple; result = aggrVarP; break; default: result = ResolveMethodCall(fullname, args); // through exception when fails break; } return true; }