private static bool ProcessJoinOverFilter( RuleProcessingContext context, System.Data.Entity.Core.Query.InternalTrees.Node joinNode, out System.Data.Entity.Core.Query.InternalTrees.Node newNode) { newNode = joinNode; TransformationRulesContext transformationRulesContext = (TransformationRulesContext)context; Command command = transformationRulesContext.Command; System.Data.Entity.Core.Query.InternalTrees.Node node1 = (System.Data.Entity.Core.Query.InternalTrees.Node)null; System.Data.Entity.Core.Query.InternalTrees.Node child0 = joinNode.Child0; if (joinNode.Child0.Op.OpType == OpType.Filter) { node1 = joinNode.Child0.Child1; child0 = joinNode.Child0.Child0; } System.Data.Entity.Core.Query.InternalTrees.Node node2 = joinNode.Child1; if (joinNode.Child1.Op.OpType == OpType.Filter && joinNode.Op.OpType != OpType.LeftOuterJoin) { node1 = node1 != null?command.CreateNode((Op)command.CreateConditionalOp(OpType.And), node1, joinNode.Child1.Child1) : joinNode.Child1.Child1; node2 = joinNode.Child1.Child0; } if (node1 == null) { return(false); } System.Data.Entity.Core.Query.InternalTrees.Node node3 = joinNode.Op.OpType != OpType.CrossJoin ? command.CreateNode(joinNode.Op, child0, node2, joinNode.Child2) : command.CreateNode(joinNode.Op, child0, node2); FilterOp filterOp = command.CreateFilterOp(); newNode = command.CreateNode((Op)filterOp, node3, node1); transformationRulesContext.SuppressFilterPushdown(newNode); return(true); }
/// <summary> /// Tries to find the filter operator corresponding to a operator key used in javascript.</summary> /// <param name="filterOp"> /// Operator key</param> /// <param name="op"> /// Operator is returned through this parameter.</param> /// <returns> /// True if "filterOp" is one of valid operator keys.</returns> internal static bool TryParse(string filterOp, out FilterOp op) { for (int i = 0; i < filterOpKeys.Length; i++) { if (filterOpKeys[i] == filterOp) { op = (FilterOp)(i); return(true); } } op = FilterOp.EQ; return(false); }
/// <summary> /// Creates and adds an AttributeValueAssertion to the filter. /// </summary> /// <param name="rfcType"> /// Filter type: EQUALITY_MATCH | GREATER_OR_EQUAL /// | LESS_OR_EQUAL | APPROX_MATCH ]. /// </param> /// <param name="attrName">Name of the attribute to be asserted.</param> /// <param name="valueArray">Value of the attribute to be asserted.</param> /// <exception cref="LdapException"> /// Cannot insert an attribute assertion in a substring /// or /// Invalid filter type for AttributeValueAssertion. /// </exception> public void AddAttributeValueAssertion(FilterOp rfcType, string attrName, sbyte[] valueArray) { if (_filterStack != null && _filterStack.Count != 0 && _filterStack.Peek() is Asn1SequenceOf) { throw new LdapException("Cannot insert an attribute assertion in a substring", LdapStatusCode.FilterError); } if (rfcType != FilterOp.EqualityMatch && rfcType != FilterOp.GreaterOrEqual && rfcType != FilterOp.LessOrEqual && rfcType != FilterOp.ApproxMatch) { throw new LdapException("Invalid filter type for AttributeValueAssertion", LdapStatusCode.FilterError); } Asn1Object current = new Asn1Tagged(new Asn1Identifier((int)rfcType, true), new RfcAttributeValueAssertion(attrName, valueArray), false); AddObject(current); }
/// <summary> /// Completes a nested filter and checks for the valid filter type. /// </summary> /// <param name="rfcType">Type of filter to complete.</param> /// <exception cref="LdapException">Mismatched ending of nested filter.</exception> public void EndNestedFilter(FilterOp rfcType) { if (rfcType == FilterOp.Not) { _filterStack.Pop(); } var topOfStackType = _filterStack.Peek().GetIdentifier().Tag; if (topOfStackType != (int)rfcType) { throw new LdapException("Mismatched ending of nested filter", LdapStatusCode.FilterError); } _filterStack.Pop(); }
/// <summary> /// Creates and adds the Asn1Tagged value for a nestedFilter: AND, OR, or /// NOT. /// Note that a Not nested filter can only have one filter, where AND /// and OR do not /// </summary> /// <param name="rfcType">Filter type: /// [AND | OR | NOT]</param> /// <exception cref="LdapException">Attempt to create a nested filter other than AND, OR or NOT</exception> public void StartNestedFilter(FilterOp rfcType) { Asn1Object current; if (rfcType == FilterOp.And || rfcType == FilterOp.Or) { current = new Asn1Tagged(new Asn1Identifier((int)rfcType, true), new Asn1SetOf(), false); } else if (rfcType == FilterOp.Not) { current = new Asn1Tagged(new Asn1Identifier((int)rfcType, true)); } else { throw new LdapException("Attempt to create a nested filter other than AND, OR or NOT", LdapStatusCode.FilterError); } AddObject(current); }
/// <summary> /// Creates and adds the Asn1Tagged value for a nestedFilter: AND, OR, or /// NOT. /// Note that a Not nested filter can only have one filter, where AND /// and OR do not. /// </summary> /// <param name="rfcType"> /// Filter type: /// [AND | OR | NOT]. /// </param> /// <exception cref="LdapException">Attempt to create a nested filter other than AND, OR or NOT.</exception> public void StartNestedFilter(FilterOp rfcType) { Asn1Object current; switch (rfcType) { case FilterOp.And: case FilterOp.Or: current = new Asn1Tagged(new Asn1Identifier((int)rfcType, true), new Asn1SetOf(), false); break; case FilterOp.Not: current = new Asn1Tagged(new Asn1Identifier((int)rfcType, true)); break; default: throw new LdapException("Attempt to create a nested filter other than AND, OR or NOT", LdapStatusCode.FilterError); } AddObject(current); }
/// <summary> /// FilterOp /// First visit the predicate (because that may contain references to /// the relop input), and then visit the relop input. No additional /// processing is required /// </summary> /// <param name="op"> the filterOp </param> /// <param name="n"> current node </param> /// <returns> </returns> public override Node Visit(FilterOp op, Node n) { // visit the predicate first, and then teh relop input VisitChildrenReverse(n); return(n); }
/// <summary> /// FilterOp handling /// /// Process the predicate child, and then the input child - since the /// predicate child will probably have references to the input. /// </summary> /// <param name="op"> </param> /// <param name="n"> </param> public override void Visit(FilterOp op, Node n) { VisitNode(n.Child1); // visit predicate first VisitNode(n.Child0); // then visit the relop input }
// <summary> // FilterOp // </summary> public override int Visit(FilterOp op, Node n) { return(VisitNode(n.Child0)); }
public override int Visit(FilterOp op, System.Data.Entity.Core.Query.InternalTrees.Node n) { return(this.VisitNode(n.Child0)); }
/// <summary> /// Converts a FilterFieldType enum to its string key used in javascript</summary> /// <param name="type"> /// A filter field type</param> /// <returns> /// The string key corresponding to the field type</returns> //internal static string ToStringKey(this FilterFieldType type) //{ // return fieldTypeKeys[(int)type]; //} /// <summary> /// Converts a FilterOp enum to its string key used in javascript</summary> /// <param name="op"> /// A filter operator</param> /// <returns> /// The string key corresponding to the filter operator</returns> internal static string ToStringKey(this FilterOp op) { return(filterOpKeys[(int)op]); }
// <summary> // FilterOp // </summary> // <remarks> // If the input to the FilterOp is a NestOp, and if the filter predicate // does not reference any of the collection Vars of the nestOp, then the // FilterOp can be simply pushed below the NestOp: // Filter(Nest(X, ...), pred) => Nest(Filter(X, pred), ...) // Note: even if the filter predicate originally referenced one of the // collection vars, as part of our bottom up traversal, the appropriate // Var was replaced by a copy of the source of the collection. So, this // transformation should always be legal. // </remarks> public override Node Visit(FilterOp op, Node n) { // First, visit my children VisitChildren(n); // see if the child is a nestOp var nestOp = n.Child0.Op as NestBaseOp; if (null != nestOp) { #if DEBUG // check to see if the predicate references any of the collection // expressions. If it doesn't, then we can push the filter down, but // even if it does it's probably OK. var predicateNodeInfo = Command.GetNodeInfo(n.Child1); foreach (var ci in nestOp.CollectionInfo) { PlanCompiler.Assert(!predicateNodeInfo.ExternalReferences.IsSet(ci.CollectionVar), "predicate references collection?"); } #endif //DEBUG // simply pull up the nest child above ourself. var nestOpNode = n.Child0; var nestOpInputNode = nestOpNode.Child0; n.Child0 = nestOpInputNode; nestOpNode.Child0 = n; // recompute node info - no need to perform anything for the predicate Command.RecomputeNodeInfo(n); Command.RecomputeNodeInfo(nestOpNode); return nestOpNode; } return n; }
public override void Visit(FilterOp op, Node n) { VisitRelOpDefault(op, n); AssertRelOpOrPhysicalOp(n.Child0.Op); AssertScalarOp(n.Child1.Op); AssertBooleanOp(n.Child1.Op); }
/// <summary> /// Converts a list of FilterLine objects to a WHERE clause usable in a SQL select query.</summary> /// <param name="lines"> /// List of FilterLine objects to convert to a WHERE clause.</param> /// <param name="filterFields"> /// Collection of FilterField objects to determine field types and check filterability of fields. /// This list is usually the filter field options list that is sent to a filter panel object. /// If this list is specified, for a filter to be considered valid, its fieldname must be /// found in the list. If the list is given null, field name is looked up in fieldExpressions, /// query or row and field type is determined by the field object in the row.</param> /// <param name="fieldExpressions"> /// An optional dictionary of field expressions. If a field's corresponding SQL expression like /// "join.field_name" is not determinable by reading in the query or the row, this list must be specified. /// When specified, this list takes priority over the query and row objects to determine the field /// expression.</param> /// <param name="query"> /// An optional SqlSelect query to determine field expressions. If a field's expression is not found /// in "fieldExpressions" dictionary, it is looked up in query object.</param> /// <param name="row"> /// An optional Row object to determine field types and expressions.</param> /// <param name="process"> /// An optional delegate to preprocess a filter line and return a filter. It should return an empty /// filter if this line should be ignored. Null if this line should be processed as usual.</param> /// <returns> /// WHERE clause.</returns> /// <remarks> /// Invalid filter lines are simply skipped, no error occurs.</remarks> public static string ToWhereString(SqlQuery query, IEnumerable <FilterLine> lines, FilterFields filterFields, IDictionary <string, string> fieldExpressions = null, Row row = null, Func <FilterLine, BaseCriteria> process = null) { if (lines == null) { throw new ArgumentNullException("lines"); } const string AND = " AND "; const string OR = " OR "; const string LPAREN = "("; const string RPAREN = ")"; //const string TRUE = "1=1"; // build a dictionary of FilterField objects if the list is specified // this list is usually the filter field options list that is sent to FilterPanel object. /*Dictionary<string, FilterField> filterFieldDict = null; * if (filterFields != null) * { * filterFieldDict = new Dictionary<string, FilterField>(StringComparer.OrdinalIgnoreCase); * foreach (FilterField f in filterFields) * { * filterFieldDict[f.GetName()] = f; * * if (f.GetTextual() != null) * filterFieldDict[f.GetTextual()] = f; * } * }*/ bool inParens = false; bool hasOr = false; StringBuilder sb = new StringBuilder(); foreach (FilterLine line in lines) { if (inParens && (line._rightParen || line._leftParen)) { sb.Append(RPAREN); inParens = false; } if (sb.Length > 0) { sb.Append(line._or ? OR : AND); if (line._or) { hasOr = true; } } if (line._leftParen) { sb.Append(LPAREN); inParens = true; } if (!line.IsValid) { throw new ArgumentOutOfRangeException("InvalidFilterLine", line.ToJson()); //sb.Append(TRUE); //continue; } if (process != null) { var filter = process(line); if (!Object.ReferenceEquals(filter, null)) { if (filter.IsEmpty) { //sb.Append(TRUE); throw new ArgumentOutOfRangeException("EmptyFilterLine", line.ToJson()); } else { sb.Append(filter.ToStringIgnoreParams()); // FIX!!!! } continue; } } string fieldName = line.Field; // if filter fields list is specified, the fieldname must exist in this list, otherwise // it may be an hacking attempt, as user tries to filter a field that he is not // represented with IFilterField filterField = null; if (filterFields != null) { filterField = filterFields.ByNameOrTextual(fieldName); if (filterField == null) { throw new ArgumentOutOfRangeException("UnknownFilterField", line.ToJson()); } //sb.Append(TRUE); //continue; } Field field = null; if (row != null) { field = row.FindField(fieldName); } /*// by default, suppose fields are string typed * FilterFieldType type = FilterFieldType.String; * // if given, determine field type by looking up in the filter field options * if (filterField != null) * type = filterField.GetType(); * // otherwise, determine field type by the class of field object * else if (field != null) * type = FilterField.ToFilterFieldType(field);*/ // to determine field expression, first look it up in fieldExpressions dictionary string fieldExpr; if (fieldExpressions == null || !fieldExpressions.TryGetValue(fieldName, out fieldExpr)) { fieldExpr = null; } if (fieldExpr == null) { if (field != null) { fieldExpr = field.Expression; } else if (query != null) { fieldExpr = query.GetExpression(fieldName); } } if (fieldExpr == null) { // field is not found anywhere, don't allow unknown fields as it may cause a script injection // attack or other types of security threats! //sb.Append(TRUE); throw new ArgumentOutOfRangeException("UnknownFilterField", line.ToJson()); //continue; } bool isNumeric = (filterField != null && (filterField.Handler == "Integer" || filterField.Handler == "Decimal")) || (filterField == null && field != null && (field is Int16Field || field is Int32Field || field is Int64Field || field is DoubleField || field is DecimalField)); // determine expression for this filter by operator type FilterOp op = line.Op; string sqlOp = SqlConditionOperators[(int)(op)]; if (op == FilterOp.IN) { StringBuilder vs = new StringBuilder(); var values = line.Values; if (line.Values != null) { foreach (var s in line.Values) { if (isNumeric) { // parse invariant decimal value for integer and float fields decimal d; if (Decimal.TryParse(s, NumberStyles.Float, Invariants.NumberFormat, out d)) { if (vs.Length > 0) { vs.Append(","); } vs.Append(d.ToInvariant()); } } else { if (vs.Length > 0) { vs.Append(","); } vs.Append(s.ToSql()); } } } if (vs.Length == 0) { //sb.Append(TRUE); throw new ArgumentOutOfRangeException("InvalidFilterLine", line.ToJson()); } else { sb.AppendFormat(sqlOp, fieldExpr, vs.ToString()); } continue; } // operator needs value if not one of "true", "false", "is null", "is not null" if (op.IsNeedsValue()) { // starts with and contains operators requires special care, as their sql expressions // already contains single quotes, so .ToSql() cannot be used if (op.IsLike()) { if (line.Value != null) { sb.AppendFormat(SqlConditionOperators[(int)(op)], fieldExpr, line.Value.Replace("'", "''")); } continue; } // parse value1 and value2 string value1 = ""; string value2 = ""; // simple loop to parse value1 and value2 in one turn for (int phase = 0; phase <= 1; phase++) { string valueText; if (phase == 0) { valueText = line.Value; } else { valueText = line.Value2; } valueText = valueText.TrimToNull(); // value must be entered if (valueText == null) { throw new ArgumentOutOfRangeException("InvalidFilterLine", line.ToJson()); } bool isDateTime = (filterField != null && (filterField.Handler == "Date")) || (filterField == null && field != null && (field is DateTimeField)); if (isNumeric) { // parse invariant decimal value for integer and float fields decimal d; if (!Decimal.TryParse(valueText, NumberStyles.Float, Invariants.NumberFormat, out d)) { throw new ArgumentOutOfRangeException("InvalidFilterLine", line.ToJson()); } valueText = d.ToInvariant(); } else if (isDateTime) { // parse iso date-time string DateTime d; if (!DateHelper.TryParseISO8601DateTime(valueText, out d)) { throw new ArgumentOutOfRangeException("InvalidFilterLine", line.ToJson()); } DateTimeKind kind = DateTimeKind.Unspecified; object dateKindObj; if (filterField != null && filterField.Params != null && filterField.Params.TryGetValue("DateKind", out dateKindObj)) { var dateKind = ((DateFilterKind)Convert.ToInt32(dateKindObj)); kind = dateKind == DateFilterKind.DateTimeLocal ? DateTimeKind.Local : (dateKind == DateFilterKind.DateTimeUTC ? DateTimeKind.Utc : DateTimeKind.Unspecified); } else if (field != null && field is DateTimeField) { kind = ((DateTimeField)field).DateTimeKind; } d = DateTimeField.ToDateTimeKind(d, kind); if (op == FilterOp.BW) { if (phase == 1) { sqlOp = "{0} >= {1} AND {0} < {2}"; d = d.AddDays(1); } } else if (phase == 0) { if (op == FilterOp.NE || op == FilterOp.EQ) { value1 = d.ToSql(); value2 = d.AddDays(1).ToSql(); if (op == FilterOp.NE) { sqlOp = "NOT ({0} >= {1} AND {0} < {2})"; } else { sqlOp = "{0} >= {1} AND {0} < {2}"; } op = FilterOp.BW; break; } else { if (op == FilterOp.GT) { op = FilterOp.GE; d = d.AddDays(1); } else if (op == FilterOp.LE) { op = FilterOp.LT; d = d.AddDays(1); } } } valueText = d.ToSql(); } else // convert simple string value to sql string (duplicate quotes) { valueText = valueText.ToSql(); } if (phase == 0) { value1 = valueText; } else { value2 = valueText; } // use second phase to parse value2 if operator is BW if (op != FilterOp.BW) { break; } } // format sql operator text with values if (op == FilterOp.BW) { sb.AppendFormat(sqlOp, fieldExpr, value1, value2); } else { sb.AppendFormat(sqlOp, fieldExpr, value1); } } else { sb.AppendFormat(sqlOp, fieldExpr); } } if (inParens) { sb.Append(RPAREN); } if (hasOr) { sb.Append(RPAREN); sb.Insert(0, LPAREN); } return(sb.ToString()); }
public FilterItem(FilterOp op, string pattern) { Op = op; Regex = new Regex(pattern); }
/// <summary> /// Checks if the operator requires a value.</summary> /// <param name="op"> /// Operator</param> /// <returns> /// True if the operator requires a value.</returns> /// <remarks> /// True, False, IsNull and IsNotNull operators doesn't require a value.</remarks> internal static bool IsNeedsValue(this FilterOp op) { return(op != FilterOp.True && op != FilterOp.False && op != FilterOp.IsNull && op != FilterOp.IsNotNull); }
/// <summary> /// Checks if the operator is one of Contains and StartsWith.</summary> /// <param name="op"> /// Operator</param> /// <returns> /// True if operator is Contains or StartsWith.</returns> internal static bool IsLike(this FilterOp op) { return(op == FilterOp.StartsWith || op == FilterOp.Contains); }
/// <summary> /// Visitor pattern method for FilterOp /// </summary> /// <param name="op"> The FilterOp being visited </param> /// <param name="n"> The Node that references the Op </param> public virtual void Visit(FilterOp op, Node n) { VisitRelOpDefault(op, n); }
public override void Visit(FilterOp op, System.Data.Entity.Core.Query.InternalTrees.Node n) { this.VisitNode(n.Child1); this.VisitNode(n.Child0); }
public override System.Data.Entity.Core.Query.InternalTrees.Node Visit(FilterOp op, System.Data.Entity.Core.Query.InternalTrees.Node n) { this.VisitChildrenReverse(n); return(n); }
public Filter(string colname, FilterOp op, object value) { this.Name = colname; this.Op = op; this.Value = value; }
/// <summary> /// Handler for a FilterOp. Usually delegates to VisitRelOpDefault. /// /// There's one special case - where we have an ISOF predicate over a ScanTable. In that case, we attempt /// to get a more "optimal" view; and return that optimal view /// /// </summary> /// <param name="op">the filterOp</param> /// <param name="n">the node tree</param> /// <returns></returns> public override Node Visit(FilterOp op, Node n) { IsOfOp typeFilter; if (IsOfTypeOverScanTable(n, out typeFilter)) { var ret = ProcessScanTable(n.Child0, (ScanTableOp)n.Child0.Op, ref typeFilter); if (typeFilter != null) { n.Child1 = VisitNode(n.Child1); n.Child0 = ret; ret = n; } return ret; } else { return VisitRelOpDefault(op, n); } }
// <summary> // Copies a filterOp // </summary> // <param name="op"> The Op to Copy </param> // <param name="n"> The Node that references the Op </param> // <returns> A copy of the original Node that references a copy of the original Op </returns> public override Node Visit(FilterOp op, Node n) { return CopyDefault(m_destCmd.CreateFilterOp(), n); }
/// <summary> /// FilterOp handling /// /// Process the predicate child, and then the input child - since the /// predicate child will probably have references to the input. /// </summary> /// <param name="op"></param> /// <param name="n"></param> public override void Visit(FilterOp op, Node n) { VisitNode(n.Child1); // visit predicate first VisitNode(n.Child0); // then visit the relop input }
public FilterApp(FilterApp lft, FilterApp rft, FilterOp fop) { m_filter = new Tuple <FilterApp, FilterApp, FilterOp>(lft, rft, fop); multi = true; }