private static IPredicate BuildPredicateTree(Func<string, IEntityField2> fieldGetter, Func<string, List<IEntityRelation>, IEntityField2> relatedFieldGetter, FilterNode filterNode, List<IEntityRelation> inferredRelationsList) { if (filterNode.NodeCount > 0) { if (filterNode.NodeType == FilterNodeType.Root && filterNode.Nodes.Count > 0) { if (filterNode.NodeCount == 1) return BuildPredicateTree(fieldGetter, relatedFieldGetter, filterNode.Nodes[0], inferredRelationsList); var predicate = new PredicateExpression(); foreach (var childNode in filterNode.Nodes) { var newPredicate = BuildPredicateTree(fieldGetter, relatedFieldGetter, childNode, inferredRelationsList); if (newPredicate != null) predicate.AddWithAnd(newPredicate); } return predicate; } else if (filterNode.NodeType == FilterNodeType.AndExpression || filterNode.NodeType == FilterNodeType.OrExpression) { var predicate = new PredicateExpression(); foreach (var childNode in filterNode.Nodes) { var newPredicate = BuildPredicateTree(fieldGetter, relatedFieldGetter, childNode, inferredRelationsList); if (newPredicate != null) { if (filterNode.NodeType == FilterNodeType.OrExpression) predicate.AddWithOr(newPredicate); else predicate.AddWithAnd(newPredicate); } } return predicate; } } else if (filterNode.ElementCount > 0) { // convert elements to IPredicate var nodePredicate = BuildPredicateFromClauseNode(fieldGetter, relatedFieldGetter, filterNode, inferredRelationsList); if (nodePredicate != null) return nodePredicate; } return null; }
/* * -> eq (equals any) * -> neq (not equals any) * -> eqc (equals any, case insensitive [on a case sensitive database]) * -> neqc (not equals any, case insensitive [on a case sensitive database]) * -> in (same as eq) * -> nin (same as ne) * -> lk (like) * -> nlk (not like) * -> nl (null) * -> nnl (not null) * -> gt (greater than) * -> gte (greater than or equal to) * -> lt (less than) * -> lte (less than or equal to) * -> ct (full text contains) * -> ft (full text free text) * -> bt (between) * -> nbt (not between) */ private static IPredicate BuildPredicateFromClauseNode(Func <string, IEntityField2> fieldGetter, Func <string, List <IEntityRelation>, IEntityField2> relatedFieldGetter, FilterNode filterNode, List <IEntityRelation> inferredRelationsList) { // there are always at least 2 elements if (filterNode.ElementCount < 2) { return(null); } var elements = filterNode.Elements; //TODO: may need to mess with relation aliases and join types in the future var relations = new List <IEntityRelation>(); var field = elements[0].IndexOf('.') == -1 ? fieldGetter(elements[0]) : relatedFieldGetter(elements[0], relations); if (field == null) { throw new ArgumentNullException("Unable to locate field " + elements[0]); } foreach (var relation in relations) { inferredRelationsList.AddIfNotExists(relation); } var comparisonOperatorStr = elements[1].ToLowerInvariant(); var valueElements = elements.Skip(2).ToArray(); var objElements = new object[valueElements.Length]; Action <string> throwINEEx = (s) => { throw new ArgumentException(string.Format("Invalid number of elements in '{0}' filter clause", s)); }; string objAlias; IPredicate predicate; switch (comparisonOperatorStr) { case ("bt"): //between case ("nbt"): //not between if (valueElements.Length < 2) { throwINEEx(comparisonOperatorStr); } objElements[0] = ConvertStringToFieldValue(field, valueElements[0]); objElements[1] = ConvertStringToFieldValue(field, valueElements[1]); objAlias = valueElements.Length == 3 ? valueElements[2] : null; predicate = new FieldBetweenPredicate(field, null, objElements[0], objElements[1], objAlias, comparisonOperatorStr == "nbt"); break; case ("in"): //same as eq case ("nin"): //same as ne case ("eq"): //equals any case ("neq"): //not equals any case ("eqc"): //equals any, case insensitive [on a case sensitive database] - only 1 element per clause with this option case ("neqc"): //not equals any, case insensitive [on a case sensitive database] - only 1 element per clause with this option if (valueElements.Length < 1) { throwINEEx(comparisonOperatorStr); } for (int i = 0; i < valueElements.Length; i++) { objElements[i] = ConvertStringToFieldValue(field, valueElements[i]); } if (objElements.Length == 1 || comparisonOperatorStr == "eqci" || comparisonOperatorStr == "neci") { predicate = new FieldCompareValuePredicate(field, null, comparisonOperatorStr.StartsWith("n") ? ComparisonOperator.NotEqual : ComparisonOperator.Equal, objElements[0]) { CaseSensitiveCollation = comparisonOperatorStr == "eqci" || comparisonOperatorStr == "neci" }; } else { if (comparisonOperatorStr.StartsWith("n")) { predicate = (EntityField2)field != objElements; } else { predicate = (EntityField2)field == objElements; } } break; case ("lk"): //like case ("nlk"): //not like if (valueElements.Length < 1) { throwINEEx(comparisonOperatorStr); } objElements[0] = ConvertStringToFieldValue(field, valueElements[0].Replace('*', '%')); objAlias = valueElements.Length == 2 ? valueElements[1] : null; predicate = new FieldLikePredicate(field, null, objAlias, (string)objElements[0], comparisonOperatorStr == "nlk"); break; case ("nl"): //null case ("nnl"): //not null predicate = new FieldCompareNullPredicate(field, null, null, comparisonOperatorStr == "nnl"); break; case ("gt"): //greater than) case ("gte"): //greater than or equal to case ("lt"): //less than case ("lte"): //less than or equal to if (valueElements.Length < 1) { throwINEEx(comparisonOperatorStr); } objElements[0] = ConvertStringToFieldValue(field, valueElements[0]); objAlias = valueElements.Length == 2 ? valueElements[1] : null; var comparisonOperator = ComparisonOperator.GreaterThan; if (comparisonOperatorStr == "gte") { comparisonOperator = ComparisonOperator.GreaterEqual; } else if (comparisonOperatorStr == "lt") { comparisonOperator = ComparisonOperator.LesserThan; } else if (comparisonOperatorStr == "lte") { comparisonOperator = ComparisonOperator.LessEqual; } predicate = new FieldCompareValuePredicate(field, null, comparisonOperator, objElements[0], objAlias); break; case ("ct"): //full text contains case ("ft"): //full text free text if (valueElements.Length < 1) { throwINEEx(comparisonOperatorStr); } objElements[0] = valueElements[0]; objAlias = valueElements.Length == 2 ? valueElements[1] : null; predicate = new FieldFullTextSearchPredicate(field, null, comparisonOperatorStr == "ct" ? FullTextSearchOperator.Contains : FullTextSearchOperator.Freetext, (string)objElements[0], objAlias); break; default: return(null); } return(predicate); }
/* -> eq (equals any) -> neq (not equals any) -> eqc (equals any, case insensitive [on a case sensitive database]) -> neqc (not equals any, case insensitive [on a case sensitive database]) -> in (same as eq) -> nin (same as ne) -> lk (like) -> nlk (not like) -> nl (null) -> nnl (not null) -> gt (greater than) -> gte (greater than or equal to) -> lt (less than) -> lte (less than or equal to) -> ct (full text contains) -> ft (full text free text) -> bt (between) -> nbt (not between) */ private static IPredicate BuildPredicateFromClauseNode(Func<string, IEntityField2> fieldGetter, Func<string, List<IEntityRelation>, IEntityField2> relatedFieldGetter, FilterNode filterNode, List<IEntityRelation> inferredRelationsList) { // there are always at least 2 elements if (filterNode.ElementCount < 2) return null; var elements = filterNode.Elements; //TODO: may need to mess with relation aliases and join types in the future var relations = new List<IEntityRelation>(); var field = elements[0].IndexOf('.') == -1 ? fieldGetter(elements[0]) : relatedFieldGetter(elements[0], relations); if (field == null) throw new ArgumentNullException("Unable to locate field " + elements[0]); foreach (var relation in relations) inferredRelationsList.AddIfNotExists(relation); var comparisonOperatorStr = elements[1].ToLowerInvariant(); var valueElements = elements.Skip(2).ToArray(); var objElements = new object[valueElements.Length]; Action<string> throwINEEx = (s) => { throw new ArgumentException(string.Format("Invalid number of elements in '{0}' filter clause", s)); }; string objAlias; IPredicate predicate; switch (comparisonOperatorStr) { case ("bt"): //between case ("nbt"): //not between if (valueElements.Length < 2) throwINEEx(comparisonOperatorStr); objElements[0] = ConvertStringToFieldValue(field, valueElements[0]); objElements[1] = ConvertStringToFieldValue(field, valueElements[1]); objAlias = valueElements.Length == 3 ? valueElements[2] : null; predicate = new FieldBetweenPredicate(field, null, objElements[0], objElements[1], objAlias, comparisonOperatorStr == "nbt"); break; case ("in"): //same as eq case ("nin"): //same as ne case ("eq"): //equals any case ("neq"): //not equals any case ("eqc"): //equals any, case insensitive [on a case sensitive database] - only 1 element per clause with this option case ("neqc"): //not equals any, case insensitive [on a case sensitive database] - only 1 element per clause with this option if (valueElements.Length < 1) throwINEEx(comparisonOperatorStr); for (int i = 0; i < valueElements.Length; i++) objElements[i] = ConvertStringToFieldValue(field, valueElements[i]); if (objElements.Length == 1 || comparisonOperatorStr == "eqci" || comparisonOperatorStr == "neci") { predicate = new FieldCompareValuePredicate(field, null, comparisonOperatorStr.StartsWith("n") ? ComparisonOperator.NotEqual : ComparisonOperator.Equal, objElements[0]) { CaseSensitiveCollation = comparisonOperatorStr == "eqci" || comparisonOperatorStr == "neci" }; } else { if (comparisonOperatorStr.StartsWith("n")) predicate = (EntityField2)field != objElements; else predicate = (EntityField2)field == objElements; } break; case ("lk"): //like case ("nlk"): //not like if (valueElements.Length < 1) throwINEEx(comparisonOperatorStr); objElements[0] = ConvertStringToFieldValue(field, valueElements[0].Replace('*', '%')); objAlias = valueElements.Length == 2 ? valueElements[1] : null; predicate = new FieldLikePredicate(field, null, objAlias, (string)objElements[0], comparisonOperatorStr == "nlk"); break; case ("nl"): //null case ("nnl"): //not null predicate = new FieldCompareNullPredicate(field, null, null, comparisonOperatorStr == "nnl"); break; case ("gt"): //greater than) case ("gte"): //greater than or equal to case ("lt"): //less than case ("lte"): //less than or equal to if (valueElements.Length < 1) throwINEEx(comparisonOperatorStr); objElements[0] = ConvertStringToFieldValue(field, valueElements[0]); objAlias = valueElements.Length == 2 ? valueElements[1] : null; var comparisonOperator = ComparisonOperator.GreaterThan; if (comparisonOperatorStr == "gte") comparisonOperator = ComparisonOperator.GreaterEqual; else if (comparisonOperatorStr == "lt") comparisonOperator = ComparisonOperator.LesserThan; else if (comparisonOperatorStr == "lte") comparisonOperator = ComparisonOperator.LessEqual; predicate = new FieldCompareValuePredicate(field, null, comparisonOperator, objElements[0], objAlias); break; case ("ct"): //full text contains case ("ft"): //full text free text if (valueElements.Length < 1) throwINEEx(comparisonOperatorStr); objElements[0] = valueElements[0]; objAlias = valueElements.Length == 2 ? valueElements[1] : null; predicate = new FieldFullTextSearchPredicate(field, null, comparisonOperatorStr == "ct" ? FullTextSearchOperator.Contains : FullTextSearchOperator.Freetext, (string)objElements[0], objAlias); break; default: return null; } return predicate; }
private static IPredicate BuildPredicateTree(Func <string, IEntityField2> fieldGetter, Func <string, List <IEntityRelation>, IEntityField2> relatedFieldGetter, FilterNode filterNode, List <IEntityRelation> inferredRelationsList) { if (filterNode.NodeCount > 0) { if (filterNode.NodeType == FilterNodeType.Root && filterNode.Nodes.Count > 0) { if (filterNode.NodeCount == 1) { return(BuildPredicateTree(fieldGetter, relatedFieldGetter, filterNode.Nodes[0], inferredRelationsList)); } var predicate = new PredicateExpression(); foreach (var childNode in filterNode.Nodes) { var newPredicate = BuildPredicateTree(fieldGetter, relatedFieldGetter, childNode, inferredRelationsList); if (newPredicate != null) { predicate.AddWithAnd(newPredicate); } } return(predicate); } else if (filterNode.NodeType == FilterNodeType.AndExpression || filterNode.NodeType == FilterNodeType.OrExpression) { var predicate = new PredicateExpression(); foreach (var childNode in filterNode.Nodes) { var newPredicate = BuildPredicateTree(fieldGetter, relatedFieldGetter, childNode, inferredRelationsList); if (newPredicate != null) { if (filterNode.NodeType == FilterNodeType.OrExpression) { predicate.AddWithOr(newPredicate); } else { predicate.AddWithAnd(newPredicate); } } } return(predicate); } } else if (filterNode.ElementCount > 0) { // convert elements to IPredicate var nodePredicate = BuildPredicateFromClauseNode(fieldGetter, relatedFieldGetter, filterNode, inferredRelationsList); if (nodePredicate != null) { return(nodePredicate); } } return(null); }