internal List<Field> ExtractQueryFieldsMeta(EntityQuery query) { List<EntityRelation> relations = relMan.Read().Object; List<Field> result = new List<Field>(); //split field string into tokens speparated by FIELDS_SEPARATOR List<string> tokens = query.Fields.Split(FIELDS_SEPARATOR).Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); //check the query tokens for widcard symbol and validate it is only that symbol - //UPDATE: allow Wildcard and field names mix. WILL NOT BE DUPLICATED //if (tokens.Count > 1 && tokens.Any(x => x == WILDCARD_SYMBOL)) // throw new Exception("Invalid query syntax. Wildcard symbol can be used only with no other fields."); Entity entity = entMan.ReadEntity(query.EntityName).Object; if (entity == null) throw new Exception(string.Format("The entity '{0}' does not exists.", query.EntityName)); //We check for wildcard symbol and if present include all fields of the queried entity bool wildcardSelectionEnabled = tokens.Any(x => x == WILDCARD_SYMBOL); if (wildcardSelectionEnabled) { result.AddRange(entity.Fields); //return result; //UPDATE: allow Wildcard and field names mix. WILL NOT BE DUPLICATED tokens.Remove(WILDCARD_SYMBOL); //UPDATE: NULL Exception is triggered if not removed. } //process only tokens do not contain RELATION_SEPARATOR foreach (var token in tokens) { if (!token.Contains(RELATION_SEPARATOR)) { //locate the field var field = entity.Fields.SingleOrDefault(x => x.Name == token); //found no field for specified token if (field == null) throw new Exception(string.Format("Invalid query result field '{0}'. The field name is incorrect.", token)); //check for duplicated field tokens and ignore them if (!result.Any(x => x.Id == field.Id)) result.Add(field); } else { var relationData = token.Split(RELATION_SEPARATOR).Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); if (relationData.Count > 2) throw new Exception(string.Format("The specified query result field '{0}' is incorrect. Only first level relation can be specified.", token)); string relationName = relationData[0]; string relationFieldName = relationData[1]; string direction = "origin-target"; if (string.IsNullOrWhiteSpace(relationName) || relationName == "$" || relationName == "$$") throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not specified.", token)); else if (!relationName.StartsWith("$")) throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not correct.", token)); else relationName = relationName.Substring(1); //check for target priority mark $$ if (relationName.StartsWith("$")) { direction = "target-origin"; relationName = relationName.Substring(1); } if (string.IsNullOrWhiteSpace(relationFieldName)) throw new Exception(string.Format("Invalid query result field '{0}'. The relation field name is not specified.", token)); Field field = result.SingleOrDefault(x => x.Name == "$" + relationName); RelationFieldMeta relationFieldMeta = null; if (field == null) { relationFieldMeta = new RelationFieldMeta(); relationFieldMeta.Name = "$" + relationName; relationFieldMeta.Direction = direction; result.Add(relationFieldMeta); } else relationFieldMeta = (RelationFieldMeta)field; relationFieldMeta.Relation = relations.SingleOrDefault(x => x.Name == relationName); if (relationFieldMeta.Relation == null) throw new Exception(string.Format("Invalid relation '{0}'. The relation does not exist.", token)); if (relationFieldMeta.Relation.TargetEntityId != entity.Id && relationFieldMeta.Relation.OriginEntityId != entity.Id) throw new Exception(string.Format("Invalid relation '{0}'. The relation does relate to queries entity.", token)); if (relationFieldMeta.Direction != direction) throw new Exception(string.Format("You are trying to query relation '{0}' from origin->target and target->origin direction in single query. This is not allowed.", token)); //Entity entity = entMan.ReadEntity(query.EntityName).Object; relationFieldMeta.TargetEntity = entMan.ReadEntity(relationFieldMeta.Relation.TargetEntityId).Object; relationFieldMeta.OriginEntity = entMan.ReadEntity(relationFieldMeta.Relation.OriginEntityId).Object; //this should not happen in a perfect (no bugs) world if (relationFieldMeta.OriginEntity == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (origin)entity is missing.", token)); if (relationFieldMeta.TargetEntity == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (target)entity is missing.", token)); relationFieldMeta.TargetField = relationFieldMeta.TargetEntity.Fields.Single(x => x.Id == relationFieldMeta.Relation.TargetFieldId); relationFieldMeta.OriginField = relationFieldMeta.OriginEntity.Fields.Single(x => x.Id == relationFieldMeta.Relation.OriginFieldId); //this should not happen in a perfect (no bugs) world if (relationFieldMeta.OriginField == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (origin)field is missing.", token)); if (relationFieldMeta.TargetField == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (target)field is missing.", token)); Entity joinToEntity = null; if (relationFieldMeta.TargetEntity.Id == entity.Id) joinToEntity = relationFieldMeta.OriginEntity; else joinToEntity = relationFieldMeta.TargetEntity; relationFieldMeta.Entity = joinToEntity; var relatedField = joinToEntity.Fields.SingleOrDefault(x => x.Name == relationFieldName); if (relatedField == null) throw new Exception(string.Format("Invalid query result field '{0}'. The relation field does not exist.", token)); //add id field of related entity if (relatedField.Name != "id") { var relatedIdField = joinToEntity.Fields.SingleOrDefault(x => x.Name == "id"); //if field already added if (!relationFieldMeta.Fields.Any(x => x.Id == relatedIdField.Id)) relationFieldMeta.Fields.Add(relatedIdField); } //if field already added if (relationFieldMeta.Fields.Any(x => x.Id == relatedField.Id)) continue; relationFieldMeta.Fields.Add(relatedField); } } return result; }
private List<Field> ExtractQueryFieldsMeta(EntityQuery query) { List<Field> result = new List<Field>(); //split field string into tokens speparated by FIELDS_SEPARATOR List<string> tokens = query.Fields.Split(FIELDS_SEPARATOR).Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); //check the query tokens for widcard symbol and validate it is only that symbol if (tokens.Count > 1 && tokens.Any(x => x == WILDCARD_SYMBOL)) throw new Exception("Invalid query syntax. Wildcard symbol can be used only with no other fields."); //get entity by name Entity entity = GetEntity(query.EntityName); if (entity == null) throw new Exception(string.Format("The entity '{0}' does not exists.", query.EntityName)); //We check for wildcard symbol and if present include all fields of the queried entity bool wildcardSelectionEnabled = tokens.Any(x => x == WILDCARD_SYMBOL); if (wildcardSelectionEnabled) { result.AddRange(entity.Fields); return result; } //process only tokens do not contain RELATION_SEPARATOR foreach (var token in tokens) { if (!token.Contains(RELATION_SEPARATOR)) { //locate the field var field = entity.Fields.SingleOrDefault(x => x.Name == token); //found no field for specified token if (field == null) throw new Exception(string.Format("Invalid query result field '{0}'. The field name is incorrect.", token)); //check for duplicated field tokens and ignore them if (!result.Any(x => x.Id == field.Id)) result.Add(field); } else { var relationData = token.Split(RELATION_SEPARATOR).Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); if (relationData.Count > 2) throw new Exception(string.Format("The specified query result field '{0}' is incorrect. Only first level relation can be specified.", token)); string relationName = relationData[0]; string relationFieldName = relationData[1]; if (string.IsNullOrWhiteSpace(relationName) || relationName == "$") throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not specified.", token)); else if (!relationName.StartsWith("$")) throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not correct.", token)); else relationName = relationName.Substring(1); if (string.IsNullOrWhiteSpace(relationFieldName)) throw new Exception(string.Format("Invalid query result field '{0}'. The relation field name is not specified.", token)); Field field = result.SingleOrDefault(x => x.Name == "$" + relationName); RelationFieldMeta relationFieldMeta = null; if (field == null) { relationFieldMeta = new RelationFieldMeta(); relationFieldMeta.Name = "$" + relationName; result.Add(relationFieldMeta); } else relationFieldMeta = (RelationFieldMeta)field; relationFieldMeta.Relation = GetRelations().SingleOrDefault(x => x.Name == relationName); if (relationFieldMeta.Relation == null) throw new Exception(string.Format("Invalid relation '{0}'. The relation does not exist.", token)); if (relationFieldMeta.Relation.TargetEntityId != entity.Id && relationFieldMeta.Relation.OriginEntityId != entity.Id) throw new Exception(string.Format("Invalid relation '{0}'. The relation does relate to queries entity.", token)); relationFieldMeta.TargetEntity = GetEntity(relationFieldMeta.Relation.TargetEntityId); relationFieldMeta.OriginEntity = GetEntity(relationFieldMeta.Relation.OriginEntityId); //this should not happen in a perfect (no bugs) world if (relationFieldMeta.OriginEntity == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (origin)entity is missing.", token)); if (relationFieldMeta.TargetEntity == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (target)entity is missing.", token)); relationFieldMeta.TargetField = relationFieldMeta.TargetEntity.Fields.Single(x => x.Id == relationFieldMeta.Relation.TargetFieldId); relationFieldMeta.OriginField = relationFieldMeta.OriginEntity.Fields.Single(x => x.Id == relationFieldMeta.Relation.OriginFieldId); //this should not happen in a perfect (no bugs) world if (relationFieldMeta.OriginField == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (origin)field is missing.", token)); if (relationFieldMeta.TargetField == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (target)field is missing.", token)); Entity joinToEntity = null; if (relationFieldMeta.TargetEntity.Id == entity.Id) joinToEntity = relationFieldMeta.OriginEntity; else joinToEntity = relationFieldMeta.TargetEntity; var relatedField = joinToEntity.Fields.SingleOrDefault(x => x.Name == relationFieldName); if (relatedField == null) throw new Exception(string.Format("Invalid query result field '{0}'. The relation field does not exist.", token)); //if field already added if (relationFieldMeta.Fields.Any(x => x.Id == relatedField.Id)) continue; relationFieldMeta.Fields.Add(relatedField); } } return result; }
private void GenerateWhereClause(QueryObject query, Entity entity, ref string sql, ref string joinSql, ref List<NpgsqlParameter> parameters, List<KeyValuePair<string, string>> overwriteArgs = null) { Field field = null; FieldType fieldType = FieldType.GuidField; string paramName = null; string completeFieldName = null; if (!string.IsNullOrWhiteSpace(query.FieldName)) { if (!query.FieldName.Contains(RELATION_NAME_RESULT_SEPARATOR)) { field = entity.Fields.SingleOrDefault(x => x.Name == query.FieldName); fieldType = field.GetFieldType(); string entityTablePrefix = GetTableNameForEntity(entity) + "."; completeFieldName = entityTablePrefix + query.FieldName; paramName = "@" + query.FieldName + "_" + Guid.NewGuid().ToString().Replace("-", ""); bool skipClause; var value = ExtractQueryFieldValue(query.FieldValue, field, overwriteArgs, out skipClause) ?? DBNull.Value; if (skipClause) return; parameters.Add(new NpgsqlParameter(paramName, value)); } else { var relationData = query.FieldName.Split(RELATION_SEPARATOR).Select(x => x.Trim()).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); if (relationData.Count > 2) throw new Exception(string.Format("The specified query filter field '{0}' is incorrect. Only first level relation can be specified.", query.FieldName)); string relationName = relationData[0]; string relationFieldName = relationData[1]; string direction = "origin-target"; if (string.IsNullOrWhiteSpace(relationName) || relationName == "$" || relationName == "$$") throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not specified.", query.FieldName)); else if (!relationName.StartsWith("$")) throw new Exception(string.Format("Invalid relation '{0}'. The relation name is not correct.", query.FieldName)); else relationName = relationName.Substring(1); //check for target priority mark $$ if (relationName.StartsWith("$")) { direction = "target-origin"; relationName = relationName.Substring(1); } if (string.IsNullOrWhiteSpace(relationFieldName)) throw new Exception(string.Format("Invalid query result field '{0}'. The relation field name is not specified.", query.FieldName)); RelationFieldMeta relationFieldMeta = new RelationFieldMeta(); relationFieldMeta.Name = "$" + relationName; relationFieldMeta.Direction = direction; relationFieldMeta.Relation = relMan.Read().Object.SingleOrDefault(x => x.Name == relationName); if (relationFieldMeta.Relation == null) throw new Exception(string.Format("Invalid relation '{0}'. The relation does not exist.", query.FieldName)); if (relationFieldMeta.Relation.TargetEntityId != entity.Id && relationFieldMeta.Relation.OriginEntityId != entity.Id) throw new Exception(string.Format("Invalid relation '{0}'. The relation does relate to queries entity.", query.FieldName)); if (relationFieldMeta.Direction != direction) throw new Exception(string.Format("You are trying to query relation '{0}' from origin->target and target->origin direction in single query. This is not allowed.", query.FieldName)); //Entity entity = entMan.ReadEntity(query.EntityName).Object; relationFieldMeta.TargetEntity = entMan.ReadEntity(relationFieldMeta.Relation.TargetEntityId).Object; relationFieldMeta.OriginEntity = entMan.ReadEntity(relationFieldMeta.Relation.OriginEntityId).Object; //this should not happen in a perfect (no bugs) world if (relationFieldMeta.OriginEntity == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (origin)entity is missing.", query.FieldName)); if (relationFieldMeta.TargetEntity == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (target)entity is missing.", query.FieldName)); relationFieldMeta.TargetField = relationFieldMeta.TargetEntity.Fields.Single(x => x.Id == relationFieldMeta.Relation.TargetFieldId); relationFieldMeta.OriginField = relationFieldMeta.OriginEntity.Fields.Single(x => x.Id == relationFieldMeta.Relation.OriginFieldId); //this should not happen in a perfect (no bugs) world if (relationFieldMeta.OriginField == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (origin)field is missing.", query.FieldName)); if (relationFieldMeta.TargetField == null) throw new Exception(string.Format("Invalid query result field '{0}'. Related (target)field is missing.", query.FieldName)); Entity joinToEntity = null; if (relationFieldMeta.TargetEntity.Id == entity.Id) joinToEntity = relationFieldMeta.OriginEntity; else joinToEntity = relationFieldMeta.TargetEntity; relationFieldMeta.Entity = joinToEntity; var relatedField = joinToEntity.Fields.SingleOrDefault(x => x.Name == relationFieldName); if (relatedField == null) throw new Exception(string.Format("Invalid query result field '{0}'. The relation field does not exist.", query.FieldName)); string relationJoinSql = string.Empty; completeFieldName = relationName + "." + relationFieldName; fieldType = relatedField.GetFieldType(); paramName = "@" + relationFieldName + "_" + Guid.NewGuid().ToString().Replace("-", ""); bool skipClause; var value = ExtractQueryFieldValue(query.FieldValue, relatedField, overwriteArgs, out skipClause) ?? DBNull.Value; if (skipClause) return; parameters.Add(new NpgsqlParameter(paramName, value)); if (relationFieldMeta.Relation.RelationType == EntityRelationType.OneToOne) { //when the relation is origin -> target entity if (relationFieldMeta.Relation.OriginEntityId == entity.Id) { relationJoinSql = string.Format(FILTER_JOIN, GetTableNameForEntity(relationFieldMeta.TargetEntity), relationName, relationName, relationFieldMeta.TargetField.Name, GetTableNameForEntity(relationFieldMeta.OriginEntity), relationFieldMeta.OriginField.Name); } else //when the relation is target -> origin, we have to query origin entity { relationJoinSql = string.Format(FILTER_JOIN, GetTableNameForEntity(relationFieldMeta.OriginEntity), relationName, relationName, relationFieldMeta.OriginField.Name, GetTableNameForEntity(relationFieldMeta.TargetEntity), relationFieldMeta.TargetField.Name); } } else if (relationFieldMeta.Relation.RelationType == EntityRelationType.OneToMany) { //when origin and target entity are different, then direction don't matter if (relationFieldMeta.Relation.OriginEntityId != relationFieldMeta.Relation.TargetEntityId) { //when the relation is origin -> target entity if (relationFieldMeta.Relation.OriginEntityId == entity.Id) { relationJoinSql = string.Format(FILTER_JOIN, GetTableNameForEntity(relationFieldMeta.TargetEntity), relationName, relationName, relationFieldMeta.TargetField.Name, GetTableNameForEntity(relationFieldMeta.OriginEntity), relationFieldMeta.OriginField.Name); } else //when the relation is target -> origin, we have to query origin entity { relationJoinSql = string.Format(FILTER_JOIN, GetTableNameForEntity(relationFieldMeta.OriginEntity), relationName, relationName, relationFieldMeta.OriginField.Name, GetTableNameForEntity(relationFieldMeta.TargetEntity), relationFieldMeta.TargetField.Name); } } else //when the origin entity is same as target entity direction matters { if (relationFieldMeta.Direction == "target-origin") { relationJoinSql = string.Format(FILTER_JOIN, GetTableNameForEntity(relationFieldMeta.OriginEntity), relationName, relationName, relationFieldMeta.OriginField.Name, GetTableNameForEntity(relationFieldMeta.TargetEntity), relationFieldMeta.TargetField.Name); } else { relationJoinSql = string.Format(FILTER_JOIN, GetTableNameForEntity(relationFieldMeta.TargetEntity), relationName, relationName, relationFieldMeta.TargetField.Name, GetTableNameForEntity(relationFieldMeta.OriginEntity), relationFieldMeta.OriginField.Name); } } } else if (relationFieldMeta.Relation.RelationType == EntityRelationType.ManyToMany) { string relationTable = "rel_" + relationFieldMeta.Relation.Name; string targetJoinAlias = relationName + "_target"; string originJoinAlias = relationName + "_origin"; string targetJoinTable = GetTableNameForEntity(relationFieldMeta.TargetEntity); string originJoinTable = GetTableNameForEntity(relationFieldMeta.OriginEntity); //if target is entity we query if (entity.Id == relationFieldMeta.TargetEntity.Id) { relationJoinSql = string.Format(FILTER_JOIN, /*LEFT OUTER JOIN*/ relationTable, /* */ targetJoinAlias /*ON*/, targetJoinAlias, /*.*/ "target_id", /* = */ targetJoinTable, /*.*/ relationFieldMeta.TargetField.Name); relationJoinSql = relationJoinSql + "\r\n" + string.Format(FILTER_JOIN, /*LEFT OUTER JOIN*/ originJoinTable, /* */ originJoinAlias /*ON*/, targetJoinAlias, /*.*/ "origin_id", /* = */ originJoinTable, /*.*/ relationFieldMeta.OriginField.Name); completeFieldName = originJoinAlias + "." + relationFieldName; } else // if origin is entity we query { relationJoinSql = string.Format(FILTER_JOIN, /*LEFT OUTER JOIN*/ relationTable, /* */ originJoinAlias /*ON*/, originJoinAlias, /*.*/ "origin_id", /* = */ originJoinTable, /*.*/ relationFieldMeta.OriginField.Name); relationJoinSql = relationJoinSql + "\r\n" + string.Format(FILTER_JOIN, /*LEFT OUTER JOIN*/ targetJoinTable, /* */ targetJoinAlias /*ON*/, originJoinAlias, /*.*/ "target_id", /* = */ targetJoinAlias, /*.*/ relationFieldMeta.TargetField.Name); completeFieldName = targetJoinAlias + "." + relationFieldName; } } if (!joinSql.Contains(relationJoinSql)) joinSql = joinSql + "\r\n" + relationJoinSql; } if ((fieldType == FieldType.MultiSelectField || fieldType == FieldType.TreeSelectField) && !(query.QueryType == QueryType.EQ || query.QueryType == QueryType.NOT)) throw new Exception("The query operator is not supported on field '" + fieldType.ToString() + "'"); } if (sql.Length > 0) sql = sql + " AND "; switch (query.QueryType) { case QueryType.EQ: { //if (fieldType == FieldType.MultiSelectField) //{ // var parameter = parameters.Single(x => x.ParameterName == paramName); // parameter.Value = new List<string>() { (string)query.FieldValue }; // sql = sql + " " + paramName + " IN ( " + completeFieldName + " )"; //} //else if (fieldType == FieldType.TreeSelectField) //{ // var parameter = parameters.Single(x => x.ParameterName == paramName); // parameter.Value = new List<Guid>() { (Guid)query.FieldValue }; // sql = sql + " " + paramName + " IN ( " + completeFieldName + " )"; //} //else if (query.FieldValue == null || DBNull.Value == query.FieldValue) sql = sql + " " + completeFieldName + " IS NULL"; else sql = sql + " " + completeFieldName + "=" + paramName; return; } case QueryType.NOT: { //if (fieldType == FieldType.MultiSelectField) //{ // var parameter = parameters.Single(x => x.ParameterName == paramName); // parameter.Value = new List<string>() { (string)query.FieldValue }; // sql = sql + " " + paramName + " NOT IN ( " + completeFieldName + " )"; //} //else if (fieldType == FieldType.TreeSelectField) //{ // var parameter = parameters.Single(x => x.ParameterName == paramName); // parameter.Value = new List<Guid>() { (Guid)query.FieldValue }; // sql = sql + " " + paramName + " NOT IN ( " + completeFieldName + " )"; //} //else if (query.FieldValue == null || DBNull.Value == query.FieldValue) sql = sql + " " + completeFieldName + " IS NOT NULL"; else sql = sql + " " + completeFieldName + "<>" + paramName; return; } case QueryType.LT: { sql = sql + " " + completeFieldName + "<" + paramName; return; } case QueryType.LTE: { sql = sql + " " + completeFieldName + "<=" + paramName; return; } case QueryType.GT: { sql = sql + " " + completeFieldName + ">" + paramName; return; } case QueryType.GTE: { sql = sql + " " + completeFieldName + ">=" + paramName; return; } case QueryType.CONTAINS: { var parameter = parameters.Single(x => x.ParameterName == paramName); parameter.Value = "%" + parameter.Value + "%"; sql = sql + " " + completeFieldName + " ILIKE " + paramName; return; } case QueryType.STARTSWITH: { var parameter = parameters.Single(x => x.ParameterName == paramName); parameter.Value = parameter.Value + "%"; sql = sql + " " + completeFieldName + " ILIKE " + paramName; return; } case QueryType.REGEX: { var regexOperator = "~"; switch (query.RegexOperator) { case QueryObjectRegexOperator.MatchCaseSensitive: regexOperator = "~"; break; case QueryObjectRegexOperator.MatchCaseInsensitive: regexOperator = "~*"; break; case QueryObjectRegexOperator.DontMatchCaseSensitive: regexOperator = "!~"; break; case QueryObjectRegexOperator.DontMatchCaseInsensitive: regexOperator = "!~*"; break; } sql = sql + " " + completeFieldName + " " + regexOperator + " " + paramName; return; } case QueryType.RELATED: { //TODO throw new NotImplementedException(); } case QueryType.NOTRELATED: { //TODO throw new NotImplementedException(); } case QueryType.AND: { if (query.SubQueries.Count == 1) GenerateWhereClause(query.SubQueries[0], entity, ref sql, ref joinSql, ref parameters, overwriteArgs); else { string andSql = string.Empty; foreach (var q in query.SubQueries) { string subQuerySql = string.Empty; GenerateWhereClause(q, entity, ref subQuerySql, ref joinSql, ref parameters, overwriteArgs); if (andSql.Length == 0) andSql = subQuerySql; else if (subQuerySql.Length > 0) andSql = andSql + " AND " + subQuerySql; } if (andSql.Length > 0) sql = sql + " ( " + andSql + " )"; } return; } case QueryType.OR: { if (query.SubQueries.Count == 1) GenerateWhereClause(query.SubQueries[0], entity, ref sql, ref joinSql, ref parameters, overwriteArgs); else { string orSql = string.Empty; foreach (var q in query.SubQueries) { string subQuerySql = string.Empty; GenerateWhereClause(q, entity, ref subQuerySql, ref joinSql, ref parameters, overwriteArgs); if (orSql.Length == 0) orSql = subQuerySql; else if (subQuerySql.Length > 0) orSql = orSql + " OR " + subQuerySql; } if (orSql.Length > 0) sql = sql + " ( " + orSql + " )"; } return; } default: throw new Exception("Not supported query type"); } }