protected virtual void GenerateFilterForCondition(DbCommand cmd, ConditionLite condition, StringBuilder sb, ref int paramIndex, ref bool firstCondition, int indentation) { string parameterName = null; if (condition.Filter != null && condition.Filter.IsEmpty()) { return; } if (firstCondition) { ; } else if (condition.LogicalOperator == LogicalOperatorLite.And) { sb.NewIndentedLine(indentation).Append("AND "); } else if (condition.LogicalOperator == LogicalOperatorLite.Or) { sb.NewIndentedLine(indentation).Append("OR "); } else { throw new NotImplementedException("Logical operator " + condition.LogicalOperator.ToString() + " not implemented"); } firstCondition = false; if (condition.Filter != null) { sb.Append(GetFilter(cmd, ref paramIndex, condition.Filter, indentation, true)); return; } IEnumerable values = condition.FieldValue as IEnumerable; IQueryBuilder queryBuilder = condition.SubQuery == null ? null : condition.SubQuery.QueryBuilder; if (condition.Operator == OperatorLite.In || condition.Operator == OperatorLite.NotIn) { if (values == null && queryBuilder == null) { throw new ArgumentException("The value for In and NotIn operators must be enumerable or a subquery", "expression"); } if (values != null) { bool hasAnyValue = values.AreThereMoreThan(0); if (!hasAnyValue) { if (condition.Operator == OperatorLite.In) { sb.Append(" 1=0"); } else { sb.Append(" 1=1"); } return; } } } PropertyMetadata propertyMetadata = null; string fieldName = condition.FieldName; string quotedColumnName = null; if (fieldName == null && condition.Operator != OperatorLite.Exists && condition.Operator != OperatorLite.NotExists) { throw new InvalidOperationException("Field Name must be not null for condition"); } if (fieldName != null) { propertyMetadata = GetPropertyMetadata(this.QueryLite.EntityType, fieldName); quotedColumnName = this.QueryLite.DataService.EntityLiteProvider.StartQuote + propertyMetadata.SqlField.ColumnName + this.QueryLite.DataService.EntityLiteProvider.EndQuote; if (condition.Operator != OperatorLite.In && condition.Operator != OperatorLite.NotIn) { sb.Append(quotedColumnName); } } if (condition.Operator == OperatorLite.IsNull) { sb.Append(" IS NULL"); return; } if (condition.Operator == OperatorLite.IsNotNull) { sb.Append(" IS NOT NULL"); return; } if (condition.Operator == OperatorLite.In || condition.Operator == OperatorLite.NotIn) { AddListCondition(cmd, condition, sb, ref paramIndex, ref indentation, values, queryBuilder, propertyMetadata, quotedColumnName); return; } else if (condition.Operator == OperatorLite.Exists || condition.Operator == OperatorLite.NotExists) { if (condition.Operator == OperatorLite.Exists) { sb.Append("EXISTS (\n"); } else { sb.Append("NOT EXISTS (\n"); } sb.Append(queryBuilder.GetSelectQuery(cmd, ref paramIndex, ++indentation)); sb.NewIndentedLine(--indentation).Append(')'); return; } var fieldReference = condition.FieldValue as FieldReference; if (fieldReference == null) { var parameter = CreateParameter(propertyMetadata, condition.FieldValue, ref paramIndex, out parameterName); cmd.Parameters.Add(parameter); } else { var fieldReferenceEntityType = fieldReference.Alias?.EntityType ?? this.QueryLite.EntityType; string fieldReferenceName = fieldReference.FieldName; PropertyMetadata fieldReferencePropertyMetadata = GetPropertyMetadata(fieldReferenceEntityType, fieldReferenceName); var aliasName = fieldReference.Alias?.Name ?? this.QueryLite.Alias?.Name; if (!string.IsNullOrEmpty(aliasName)) { parameterName = aliasName + "."; } else { parameterName = string.Empty; } parameterName += this.QueryLite.DataService.EntityLiteProvider.StartQuote + fieldReferencePropertyMetadata.SqlField.ColumnName + this.QueryLite.DataService.EntityLiteProvider.EndQuote; } switch (condition.Operator) { case OperatorLite.Contains: sb.Append(" LIKE " + QueryLite.DataService.EntityLiteProvider.Concat("'%'", parameterName, "'%'")); break; case OperatorLite.Equals: sb.Append(" = ").Append(parameterName); break; case OperatorLite.Greater: sb.Append(" > ").Append(parameterName); break; case OperatorLite.GreaterOrEquals: sb.Append(" >= ").Append(parameterName); break; case OperatorLite.Less: sb.Append(" < ").Append(parameterName); break; case OperatorLite.LessOrEquals: sb.Append(" <= ").Append(parameterName); break; case OperatorLite.NotContains: sb.Append(" NOT LIKE " + QueryLite.DataService.EntityLiteProvider.Concat("'%'", parameterName, "'%'")); break; case OperatorLite.NotEquals: sb.Append(" <> ").Append(parameterName); break; case OperatorLite.NotStartsWith: sb.Append(" NOT LIKE " + QueryLite.DataService.EntityLiteProvider.Concat(parameterName, "'%'")); break; case OperatorLite.StartsWith: sb.Append(" LIKE " + QueryLite.DataService.EntityLiteProvider.Concat(parameterName, "'%'")); break; case OperatorLite.IsDescendantOf: sb.Append(".IsDescendantOf(" + parameterName + ") = 1"); break; case OperatorLite.IsChildOf: sb.Append(".GetAncestor(1) = " + parameterName); break; case OperatorLite.IsGrandChildOf: sb.Append(".GetAncestor(2) = " + parameterName); break; case OperatorLite.HierarchyLevelEquals: sb.Append(".GetLevel() = " + parameterName); break; case OperatorLite.STEquals: sb.Append(".STEquals(" + parameterName + ") = 1"); break; case OperatorLite.STIntersects: sb.Append(".STIntersects(" + parameterName + ") = 1"); break; case OperatorLite.STDistanceLess: case OperatorLite.STDistanceLessOrEquals: string pname = QueryLite.DataService.EntityLiteProvider.ParameterPrefix + "P" + paramIndex.ToString(); cmd.Parameters.AddWithValue(pname, condition.Parameter); paramIndex++; sb.Append(".STDistance(" + parameterName + ") " + (condition.Operator == OperatorLite.STDistanceLess ? "< " : "<= ") + pname); break; default: throw new NotImplementedException("operator " + condition.Operator.ToString() + " not implemented yet"); } }
private void AddListCondition(DbCommand cmd, ConditionLite condition, StringBuilder sb, ref int paramIndex, ref int indentation, IEnumerable values, IQueryBuilder queryBuilder, PropertyMetadata propertyMetadata, string quotedColumnName) { if (values != null) { bool firstValue = true; var isNumericField = propertyMetadata.PropertyInfo.PropertyType.IsNumericType(); var undelyingFieldType = propertyMetadata.PropertyInfo.PropertyType.UndelyingType(); var isStringField = propertyMetadata.PropertyInfo.PropertyType == typeof(string); if ((isNumericField || isStringField) && values.AreThereMoreThan(8)) { bool firstChunk = true; int valueCount = 0; sb.Append("("); foreach (object v in values) { object value = v; if (valueCount % 1000 == 0) { firstValue = true; if (firstChunk) { firstChunk = false; } else { sb.Append(") ").Append(condition.Operator == OperatorLite.In ? " OR " : " AND "); } sb.Append(quotedColumnName).Append(condition.Operator == OperatorLite.In ? " IN (" : " NOT IN ("); } string valueStr = null; if (value == null) { valueStr = "NULL"; } else { if (isNumericField && !value.IsNumeric()) { try { value = Convert.ChangeType(value, undelyingFieldType, CultureInfo.InvariantCulture); } catch (Exception ex) { throw new ArgumentException($"A non numeric value has been found for {condition.Operator} operator and field {propertyMetadata.PropertyInfo.Name}", ex); } } valueStr = Convert.ToString(value, CultureInfo.InvariantCulture); if (isStringField) { valueStr = "'" + valueStr.Replace("'", "''") + "'"; } } if (firstValue) { firstValue = false; } else { sb.Append(", "); } sb.Append(valueStr); valueCount++; } sb.Append("))"); } else { sb.Append(quotedColumnName).Append(condition.Operator == OperatorLite.In ? " IN (": " NOT IN ("); string parameterName; foreach (object value in values) { var param = CreateParameter(propertyMetadata, value, ref paramIndex, out parameterName); cmd.Parameters.Add(param); if (firstValue) { firstValue = false; } else { sb.Append(", "); } sb.Append(parameterName); } sb.Append(")"); } } else { sb.Append(quotedColumnName).Append(condition.Operator == OperatorLite.In ? " IN (" : " NOT IN ("); sb.Append('\n').Append(queryBuilder.GetSelectQuery(cmd, ref paramIndex, ++indentation)); sb.NewIndentedLine(--indentation); sb.Append(")"); } }
protected virtual void GenerateFilterForCondition(DbCommand cmd, ConditionLite condition, StringBuilder sb, ref int paramIndex, ref bool firstCondition) { if (condition.Filter != null && condition.Filter.IsEmpty()) return; if (firstCondition) { ;} else if (condition.LogicalOperator == LogicalOperatorLite.And) sb.Append("\n AND "); else if (condition.LogicalOperator == LogicalOperatorLite.Or) sb.Append("\n OR"); else throw new NotImplementedException("Logical operator " + condition.LogicalOperator.ToString() + " not implemented"); firstCondition = false; if (condition.Filter != null) { sb.Append(GetFilter(cmd, ref paramIndex, condition.Filter)); return; } IEnumerable values = condition.FieldValue as IEnumerable; IQueryBuilder queryBuilder = condition.SubQuery == null ? null : condition.SubQuery.QueryBuilder; if (condition.Operator == OperatorLite.In || condition.Operator == OperatorLite.NotIn) { if (values == null && queryBuilder == null) throw new ArgumentException("The value for In and NotIn operators must be enumerable or a query builder", "expression"); int count; if (values != null) { ICollection collection = values as ICollection; Array array = values as Array; if (collection != null) count = collection.Count; else if (array != null) count = array.Length; else count = values.Cast<object>().Count(); if (count == 0) { if (condition.Operator == OperatorLite.In) { sb.Append(" 1=0"); } else { sb.Append(" 1=1"); } return; } } } PropertyMetadata propertyMetadata = null; string fieldName = condition.FieldName; if (!QueryLite.EntityType.GetEntityMetadata().Properties.TryGetValue(fieldName, out propertyMetadata)) { throw new ArgumentException("Field " + condition.FieldName + " cannot be used in a filter because it is not a property of " + QueryLite.EntityType.Name); } if (propertyMetadata.IsLocalizedFiled) { fieldName = CurrentLanguageService.GetSufixedLocalizedFieldName(fieldName); if (string.IsNullOrEmpty(fieldName)) { throw new InvalidOperationException("Cannot sort by localized property " + fieldName + " because no field name has been found for the current language: " + CurrentLanguageService.CurrentLanguageCode); } if (!QueryLite.EntityType.GetEntityMetadata().Properties.TryGetValue(fieldName, out propertyMetadata)) { throw new ArgumentException("Field " + fieldName + " cannot be used in a filter because it is not a property of " + QueryLite.EntityType.Name); } } if (propertyMetadata.SqlField == null) { throw new ArgumentException("Field " + fieldName + " cannot be used in a filter because it has no metadata"); } sb.Append(this.QueryLite.DataService.EntityLiteProvider.StartQuote).Append(propertyMetadata.SqlField.ColumnName).Append(this.QueryLite.DataService.EntityLiteProvider.EndQuote); if (condition.Operator == OperatorLite.IsNull) { sb.Append(" IS NULL"); return; } if (condition.Operator == OperatorLite.IsNotNull) { sb.Append(" IS NOT NULL"); return; } if (condition.Operator == OperatorLite.In || condition.Operator == OperatorLite.NotIn) { if (condition.Operator == OperatorLite.In) sb.Append(" IN ("); else sb.Append(" NOT IN ("); if (values != null) { bool firstValue = true; foreach (object value in values) { var param = CreateParameter(propertyMetadata, value, ref paramIndex); cmd.Parameters.Add(param); if (firstValue) firstValue = false; else sb.Append(", "); sb.Append(param.ParameterName); } } else { sb.Append(queryBuilder.GetSelectQuery(cmd, ref paramIndex)); } sb.Append(")"); return; } var parameter = CreateParameter(propertyMetadata, condition.FieldValue, ref paramIndex); cmd.Parameters.Add(parameter); switch (condition.Operator) { case OperatorLite.Contains: sb.Append(" LIKE " + QueryLite.DataService.EntityLiteProvider.Concat("'%'", parameter.ParameterName, "'%'")); break; case OperatorLite.Equals: sb.Append(" = ").Append(parameter.ParameterName); break; case OperatorLite.Greater: sb.Append(" > ").Append(parameter.ParameterName); break; case OperatorLite.GreaterOrEquals: sb.Append(" >= ").Append(parameter.ParameterName); break; case OperatorLite.Less: sb.Append(" < ").Append(parameter.ParameterName); break; case OperatorLite.LessOrEquals: sb.Append(" <= ").Append(parameter.ParameterName); break; case OperatorLite.NotContains: sb.Append(" NOT LIKE " + QueryLite.DataService.EntityLiteProvider.Concat("'%'", parameter.ParameterName, "'%'")); break; case OperatorLite.NotEquals: sb.Append(" <> ").Append(parameter.ParameterName); break; case OperatorLite.NotStartsWith: sb.Append(" NOT LIKE " + QueryLite.DataService.EntityLiteProvider.Concat(parameter.ParameterName, "'%'")); break; case OperatorLite.StartsWith: sb.Append(" LIKE " + QueryLite.DataService.EntityLiteProvider.Concat(parameter.ParameterName, "'%'")); break; case OperatorLite.IsDescendantOf: sb.Append(".IsDescendantOf(" + parameter.ParameterName + ") = 1"); break; case OperatorLite.IsChildOf: sb.Append(".GetAncestor(1) = " + parameter.ParameterName); break; case OperatorLite.IsGrandChildOf: sb.Append(".GetAncestor(2) = " + parameter.ParameterName); break; case OperatorLite.HierarchyLevelEquals: sb.Append(".GetLevel() = " + parameter.ParameterName); break; case OperatorLite.STEquals: sb.Append(".STEquals(" + parameter.ParameterName + ") = 1"); break; case OperatorLite.STIntersects: sb.Append(".STIntersects(" + parameter.ParameterName + ") = 1"); break; case OperatorLite.STDistanceLess: case OperatorLite.STDistanceLessOrEquals: string parameterName = QueryLite.DataService.EntityLiteProvider.ParameterPrefix + "P" + paramIndex.ToString(); cmd.Parameters.AddWithValue(parameterName, condition.Parameter); paramIndex++; sb.Append(".STDistance(" + parameter.ParameterName + ") " + (condition.Operator == OperatorLite.STDistanceLess ? "< " : "<= ") + parameterName); break; default: throw new NotImplementedException("operator " + condition.Operator.ToString() + " not implemented yet"); } }