public static ColumnMethodCallEvaluator GetMethodEvaluator(Type datatype, int columnLength, MethodCallExpression CallExpression) { ColumnMethodCallEvaluator evaluator = new ColumnMethodCallEvaluator(); evaluator.GetColumnValue = Serializer.Simple.ConverterHelper.GetBytesToValue(datatype); if (evaluator.GetColumnValue == null) { throw new Exception(datatype.Name + " type does not supported to be used as a parameter yet."); } if (CallExpression.Method.ReturnType != typeof(bool)) { throw new Exception("Call method must return a boolean"); } List <Expression> arguments = new List <Expression>(); ParameterExpression objectPara = Expression.Parameter(typeof(object)); foreach (var item in CallExpression.Arguments) { if (item.NodeType == ExpressionType.MemberAccess) { var expression = Expression.Convert(objectPara, datatype); arguments.Add(expression); } else { arguments.Add(item); } } MethodCallExpression newexpression = Expression.Call(CallExpression.Method, arguments.ToArray()); evaluator.Check = Expression.Lambda <Func <object, bool> >(newexpression, objectPara).Compile(); return(evaluator); }
/// <summary> /// prase the filter collection and get an execution plan. /// </summary> /// <returns></returns> public static ExecutionPlan GetExecutionPlan(Filter <TKey, TValue> filter) { ExecutionPlan executionplan = new ExecutionPlan(); //first check order by field. if (filter.OrderByPrimaryKey) { // does not support range with primary key yet, will be supported later. Range <byte[]> primaryrange = getRange(filter.store.StoreSetting.PrimaryKey, filter.items); if (primaryrange != null) { executionplan.startCollection = filter.store.primaryIndex.getCollection(primaryrange.lower, primaryrange.upper, primaryrange.lowerOpen, primaryrange.upperOpen, filter.Ascending); } else { executionplan.startCollection = filter.store.primaryIndex.allItemCollection(filter.Ascending); } // executionplan.OrderBySettled = true; executionplan.hasStartCollection = true; } else { if (!string.IsNullOrEmpty(filter.OrderByFieldName)) { if (filter.store.Indexes.HasIndex(filter.OrderByFieldName)) { Range <byte[]> range = getRange(filter.OrderByFieldName, filter.items); if (range != null) { executionplan.startCollection = filter.store.Indexes.getIndex(filter.OrderByFieldName).GetCollection(range.lower, range.upper, range.lowerOpen, range.upperOpen, filter.Ascending); } else { executionplan.startCollection = filter.store.Indexes.getIndex(filter.OrderByFieldName).AllItems(filter.Ascending); } // executionplan.OrderBySettled = true; executionplan.hasStartCollection = true; } } } // check the primary key index. Range <byte[]> primarykeyrange = getRange(filter.store.StoreSetting.PrimaryKey, filter.items); if (primarykeyrange != null) { executionplan.startCollection = filter.store.primaryIndex.getCollection(primarykeyrange.lower, primarykeyrange.upper, primarykeyrange.lowerOpen, primarykeyrange.upperOpen, filter.Ascending); executionplan.hasStartCollection = true; } // check all index fields that has been used in the filter. foreach (var item in filter.store.Indexes.items) { Range <byte[]> indexrange = getRange(item.FieldName, filter.items); if (indexrange != null) { executionplan.indexRanges.Add(item.FieldName, indexrange); } } // now parse columns. All query where condition item must be in columns, otherwise this will be a problem. foreach (var item in filter.items) { Columns.IColumn <TValue> column; column = filter.store.GetColumn(item.FieldOrProperty); if (column != null) { ColumnScan colplan = new ColumnScan(); colplan.ColumnName = column.FieldName; colplan.relativeStartPosition = column.relativePosition; colplan.length = column.Length; colplan.Evaluator = ColumnEvaluator.GetEvaluator(column.DataType, item.Compare, item.Value, column.Length); executionplan.scanColumns.Add(colplan); } else { throw new Exception("filter field must be index or column, add them to colomn or index when creating the store, otherwise use the fullscan option"); } } foreach (var item in filter.InItems) { Columns.IColumn <TValue> column; column = filter.store.GetColumn(item.Key); if (column != null) { ColumnScan colplan = new ColumnScan(); colplan.ColumnName = column.FieldName; colplan.relativeStartPosition = column.relativePosition; colplan.length = column.Length; colplan.Evaluator = ColumnInEvaluator.GetInEvaluator(column.DataType, item.Value, column.Length); executionplan.scanColumns.Add(colplan); } else { throw new Exception("filter field must be index or column, add them to colomn or index when creating the store, otherwise use the fullscan option"); } } /// for the methods calls. foreach (var item in filter.calls) { MemberExpression memberaccess = null; foreach (var xitem in item.Arguments) { if (xitem.NodeType == ExpressionType.MemberAccess) { memberaccess = xitem as MemberExpression; } } if (memberaccess == null) { throw new Exception("Method call require use one of the Fields or Property as parameters"); } string fieldname = memberaccess.Member.Name; Columns.IColumn <TValue> column; column = filter.store.GetColumn(fieldname); if (column != null) { ColumnScan colplan = new ColumnScan(); colplan.ColumnName = column.FieldName; colplan.relativeStartPosition = column.relativePosition; colplan.length = column.Length; colplan.Evaluator = ColumnMethodCallEvaluator.GetMethodEvaluator(column.DataType, column.Length, item); executionplan.scanColumns.Add(colplan); } else { throw new Exception("methed call parameter must be a column, add the field to colomn creating creating the store, otherwise use the fullscan option"); } } /// verify the plan. or optimize it. if (!executionplan.hasStartCollection) { //make one of the range. pick any one now. should be pick by the optimizer. foreach (var item in executionplan.indexRanges) { IIndex <TValue> index = filter.store.Indexes.getIndex(item.Key); if (index != null) { executionplan.startCollection = index.GetCollection(item.Value.lower, item.Value.upper, item.Value.lowerOpen, item.Value.upperOpen, filter.Ascending); executionplan.hasStartCollection = true; executionplan.indexRanges.Remove(item.Key); break; } } if (!executionplan.hasStartCollection) { executionplan.startCollection = filter.store.primaryIndex.allItemCollection(filter.Ascending); executionplan.hasStartCollection = true; } } return(executionplan); }