internal static List <PrefetchField> GetPrefetchFieldsOne(CSTable table, List <string> fieldList, List <string> aliasList, CSJoinList joinList, string[] prefetchPaths) { List <PrefetchField> prefetchFields = new List <PrefetchField>(); foreach (CSSchemaField schemaField in table.Schema.Fields) { bool prefetch = schemaField.Prefetch; string fieldName = schemaField.Name; prefetch |= (prefetchPaths != null && prefetchPaths.Any(s => { if (s.IndexOf('.') > 0) { s = s.Substring(0, s.IndexOf('.')); } return(s == fieldName); })); if (schemaField.Relation != null && schemaField.Relation.RelationType == CSSchemaRelationType.ManyToOne && prefetch) { CSJoin join = new CSJoin(schemaField.Relation, table.TableAlias); joinList.Add(join); PrefetchField prefetchField = new PrefetchField(); prefetchField.SchemaField = schemaField; foreach (string columnName in schemaField.Relation.ForeignSchema.ColumnsToRead) { string alias = CSNameGenerator.NextFieldAlias; fieldList.Add(join.RightAlias + "." + columnName); aliasList.Add(alias); prefetchField.AliasMap[alias] = columnName; } prefetchFields.Add(prefetchField); } } return(prefetchFields); }
private void Populate() { if (Populated) { return; } if (Relation != null && RelationObject != null && Relation.RelationType == CSSchemaRelationType.OneToMany && RelationObject.IsNew) { _objectArray = new List <TObjectType>(); Populated = true; return; } CSTable table = new CSTable(Schema); //string mainAlias = CSHelper.NextTableAlias; List <string> columnList = new List <string>(Schema.ColumnsToRead.Count); List <string> aliasList = new List <string>(Schema.ColumnsToRead.Count); Dictionary <string, string> aliasMap = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (string columnName in Schema.ColumnsToRead) { string alias = CSNameGenerator.NextFieldAlias; columnList.Add(table.TableAlias + "." + columnName); aliasList.Add(alias); aliasMap.Add(alias, columnName); } CSJoinList filterJoins = new CSJoinList(); List <PrefetchField> prefetchFields = CSObject.GetPrefetchFieldsOne(table, columnList, aliasList, filterJoins, PrefetchPaths); CSFilter whereFilter; if (PrefetchFilter != null) { whereFilter = new CSFilter(DB.QuoteField(table.TableAlias + "." + PrefetchFilter.ForeignKey) + " in (" + PrefetchFilter.InStatement + ")", PrefetchFilter.Parameters); } else { string parsedFilterExpression = CSExpressionParser.ParseFilter(Filter.Expression, Schema, table.TableAlias, filterJoins); whereFilter = new CSFilter(parsedFilterExpression, Filter.Parameters); CSFilter relationFilter = BuildRelationFilter(table.TableAlias); whereFilter = whereFilter.And(CSExpressionParser.ParseFilter(relationFilter.Expression, Schema, table.TableAlias, filterJoins), relationFilter.Parameters); } string parsedOrderBy = CSExpressionParser.ParseOrderBy(OrderBy, Schema, table.TableAlias, filterJoins); string sqlQuery = DB.BuildSelectSQL(table.TableName, table.TableAlias, columnList.ToArray(), aliasList.ToArray(), filterJoins.BuildJoinExpressions(), whereFilter.Expression, parsedOrderBy, StartRecord, MaxRecords, true, false); _objectArray = GetObjects(sqlQuery, whereFilter.Parameters, aliasMap, prefetchFields); if (Schema.KeyColumns.Count == 1) { string columnName = Schema.KeyColumns[0].Name; _objectMap = new Dictionary <object, TObjectType>(); foreach (TObjectType csObject in _objectArray) { _objectMap.Add(csObject.Data["#" + columnName].Value, csObject); } } foreach (CSSchemaField prefetchField in GetPrefetchFieldsMany()) { CSRelation relation = prefetchField.Relation; Dictionary <object, TObjectType> prefetchMap = new Dictionary <object, TObjectType>(); // Creates empty lists in each object of this list foreach (TObjectType csObject in _objectArray) { prefetchMap[csObject.Data["#" + relation.LocalKey].Value] = csObject; CSList relationCollection = (CSList)Activator.CreateInstance(prefetchField.FieldType); relationCollection.Relation = relation; relationCollection.RelationObject = csObject; relationCollection.InitializePrefetch(); csObject.Data[prefetchField.Name].ValueDirect = relationCollection; csObject.Data[prefetchField.Name].ValueState = CSFieldValueState.Read; } Type objectType = relation.ForeignSchema.ClassType; CSList csList = (CSList)Activator.CreateInstance(typeof(CSList <>).MakeGenericType(objectType)); //string prefetchTableAlias = CSNameGenerator.NextTableAlias; string prefetchFilter = DB.BuildSelectSQL(table.TableName, table.TableAlias, new[] { table.TableAlias + "." + relation.LocalKey }, new[] { CSNameGenerator.NextFieldAlias }, filterJoins.BuildJoinExpressions(), whereFilter.Expression, parsedOrderBy, StartRecord, MaxRecords, true, true); csList.PrefetchFilter = new PrefetchFilter(relation.ForeignKey, prefetchFilter, whereFilter.Parameters); if (PrefetchPaths != null && PrefetchPaths.Length > 0) { List <string> newPrefetchPaths = new List <string>(); foreach (string path in PrefetchPaths) { if (path.StartsWith(prefetchField.Name + ".")) { newPrefetchPaths.Add(path.Substring(prefetchField.Name.Length + 1)); } } if (newPrefetchPaths.Count > 0) { csList.PrefetchPaths = newPrefetchPaths.ToArray(); } } foreach (CSObject csObject in csList) { object localKey = csObject.Data["#" + relation.ForeignKey].ValueDirect; CSList relationCollection = (CSList)prefetchMap[localKey].Data[prefetchField.Name].ValueDirect; relationCollection.AddFromPrefetch(csObject); } } Populated = true; }
private static object EvalVariable(string var, QueryExpression parentQuery) { Match match = _regexVar.Match(var); if (!match.Success) { throw new CSExpressionException("Object [" + var + "] is unknown"); } List <string> fieldNames = new List <string>(); foreach (Capture capture in match.Groups["Object"].Captures) { fieldNames.Add(capture.Value); } QueryExpression subExpression = null; CSTable currentTable = parentQuery.Table; string fieldName = null; for (int i = 0; i < fieldNames.Count; i++) { bool isLast = (i == fieldNames.Count - 1); CSJoin currentJoin = null; CSSchemaField schemaField = currentTable.Schema.Fields[fieldNames[i]]; if (schemaField == null) { throw new CSException("Error in expression. [" + fieldNames[i] + "] is not a valid field name"); } if (schemaField.Relation != null) { switch (schemaField.Relation.RelationType) { case CSSchemaRelationType.OneToMany: { if (subExpression != null) { throw new CSExpressionException("Error in expression [" + var + "]: Multiple *ToMany relations"); } subExpression = new QueryExpression(schemaField.Relation.ForeignSchema); subExpression.Joins = new CSJoinList(); subExpression.Expression = currentTable.TableAlias + "." + currentTable.Schema.DB.QuoteField(schemaField.Relation.LocalKey) + "=" + subExpression.Table.TableAlias + "." + currentTable.Schema.DB.QuoteField(schemaField.Relation.ForeignKey); } break; case CSSchemaRelationType.ManyToMany: { if (subExpression != null) { throw new CSExpressionException("Error in expression [" + var + "]: Multiple *ToMany relations"); } subExpression = new QueryExpression(schemaField.Relation.ForeignSchema); subExpression.Joins = new CSJoinList(); currentJoin = new CSJoin(); currentJoin.LeftSchema = schemaField.Relation.ForeignSchema; currentJoin.LeftTable = subExpression.Table.TableName; currentJoin.LeftAlias = subExpression.Table.TableAlias; currentJoin.RightTable = schemaField.Relation.LinkTable; currentJoin.RightAlias = CSNameGenerator.NextTableAlias; currentJoin.LeftColumn = schemaField.Relation.ForeignKey; currentJoin.RightColumn = schemaField.Relation.ForeignLinkKey; currentJoin.Type = CSJoinType.Inner; subExpression.Joins.Add(currentJoin); subExpression.Expression = currentJoin.RightAlias + "." + currentTable.Schema.DB.QuoteField(schemaField.Relation.LocalLinkKey) + "=" + currentTable.TableAlias + "." + currentTable.Schema.DB.QuoteField(schemaField.Relation.LocalKey); currentJoin = null; } break; case CSSchemaRelationType.ManyToOne: { if (!isLast) { if (subExpression != null) // meaning we already encountered a *toMany relation { currentJoin = new CSJoin(schemaField.Relation, subExpression.Table.TableAlias); if (subExpression.Joins.Contains(currentJoin)) { currentJoin = subExpression.Joins.GetExistingJoin(currentJoin); } else { subExpression.Joins.Add(currentJoin); } } else { currentJoin = new CSJoin(schemaField.Relation, currentTable.TableAlias); if (parentQuery.Joins.Contains(currentJoin)) { currentJoin = parentQuery.Joins.GetExistingJoin(currentJoin); } else { parentQuery.Joins.Add(currentJoin); } } } } break; } if (!isLast) { if (currentJoin != null) { currentTable = new CSTable(schemaField.Relation.ForeignSchema, currentJoin.RightAlias); } else { if (subExpression != null) { currentTable = new CSTable(schemaField.Relation.ForeignSchema, subExpression.Table.TableAlias); } else { currentTable = new CSTable(schemaField.Relation.ForeignSchema); } } } else { fieldName = currentTable.Schema.DB.QuoteField(currentTable.TableAlias + "." + schemaField.Relation.LocalKey); } } else { fieldName = currentTable.Schema.DB.QuoteField(currentTable.TableAlias + "." + schemaField.MappedColumn.Name); } } if (subExpression != null) { subExpression.FieldName = fieldName; return(subExpression); } else { //if (fieldName != null) return(fieldName); } }
public QueryExpression(CSSchema schema) { Table = new CSTable(schema); }
public QueryExpression(CSSchema schema, string tableAlias) { Table = new CSTable(schema, tableAlias); }
internal bool ReadFields(CSStringCollection columnList, CSStringCollection keyList, List <object> valueList) { List <string> fieldList = new List <string>(); List <string> aliasList = new List <string>(); Dictionary <string, string> fieldAliasMap = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); CSFilter whereClause = new CSFilter(); CSTable table = new CSTable(_schema); CSParameterCollection parameters = new CSParameterCollection(); foreach (CSSchemaColumn schemaColumn in _schema.Columns) { if (keyList.Contains(schemaColumn.Name)) { CSParameter parameter = parameters.Add(); parameter.Value = valueList[keyList.IndexOf(schemaColumn.Name)]; whereClause = whereClause.And(table.TableAlias + "." + _schema.DB.QuoteField(schemaColumn.Name) + "=" + parameter.Name); _fieldData["#" + schemaColumn.Name].ValueDirect = parameter.Value; _fieldData["#" + schemaColumn.Name].ValueState = CSFieldValueState.Read; } else if (columnList.Contains(schemaColumn.Name)) { string alias = CSNameGenerator.NextFieldAlias; fieldList.Add(table.TableAlias + "." + schemaColumn.Name); aliasList.Add(alias); fieldAliasMap[alias] = schemaColumn.Name; } } /** Build query for prefetch of relations **/ CSJoinList joinList = new CSJoinList(); List <PrefetchField> prefetchFields = GetPrefetchFieldsOne(table, fieldList, aliasList, joinList, null); if (whereClause.Expression.Length == 0) { return(false); } if (fieldList.Count == 0) { return(true); } string sqlQuery = _schema.DB.BuildSelectSQL(table.TableName, table.TableAlias, fieldList.ToArray(), aliasList.ToArray(), joinList.BuildJoinExpressions(), whereClause.Expression, null, 1, 1, true, false); using (CSTransaction csTransaction = new CSTransaction(_schema)) { using (ICSDbReader dataReader = _schema.DB.CreateReader(sqlQuery, parameters)) { if (!dataReader.Read()) { return(false); } FromDataReader(dataReader, fieldAliasMap); foreach (PrefetchField prefetchField in prefetchFields) { ReadRelationToOne(prefetchField.SchemaField, dataReader, prefetchField.AliasMap); } } csTransaction.Commit(); } return(true); }
private static object EvalVariable(string var, QueryExpression parentQuery) { Match match = _regexVar.Match(var); if (!match.Success) throw new CSExpressionException("Object [" + var + "] is unknown"); List<string> fieldNames = new List<string>(); foreach (Capture capture in match.Groups["Object"].Captures) fieldNames.Add(capture.Value); QueryExpression subExpression = null; CSTable currentTable = parentQuery.Table; string fieldName = null; for (int i = 0; i < fieldNames.Count; i++) { bool isLast = (i == fieldNames.Count - 1); CSJoin currentJoin = null; CSSchemaField schemaField = currentTable.Schema.Fields[fieldNames[i]]; if (schemaField == null) throw new CSException("Error in expression. [" + fieldNames[i] + "] is not a valid field name"); if (schemaField.Relation != null) { switch (schemaField.Relation.RelationType) { case CSSchemaRelationType.OneToMany: { if (subExpression != null) throw new CSExpressionException("Error in expression [" + var + "]: Multiple *ToMany relations"); subExpression = new QueryExpression(schemaField.Relation.ForeignSchema); subExpression.Joins = new CSJoinList(); subExpression.Expression = currentTable.TableAlias + "." + currentTable.Schema.DB.QuoteField(schemaField.Relation.LocalKey) + "=" + subExpression.Table.TableAlias + "." + currentTable.Schema.DB.QuoteField(schemaField.Relation.ForeignKey); } break; case CSSchemaRelationType.ManyToMany: { if (subExpression != null) throw new CSExpressionException("Error in expression [" + var + "]: Multiple *ToMany relations"); subExpression = new QueryExpression(schemaField.Relation.ForeignSchema); subExpression.Joins = new CSJoinList(); currentJoin = new CSJoin(); currentJoin.LeftSchema = schemaField.Relation.ForeignSchema; currentJoin.LeftTable = subExpression.Table.TableName; currentJoin.LeftAlias = subExpression.Table.TableAlias; currentJoin.RightTable = schemaField.Relation.LinkTable; currentJoin.RightAlias = CSNameGenerator.NextTableAlias; currentJoin.LeftColumn = schemaField.Relation.ForeignKey; currentJoin.RightColumn = schemaField.Relation.ForeignLinkKey; currentJoin.Type = CSJoinType.Inner; subExpression.Joins.Add(currentJoin); subExpression.Expression = currentJoin.RightAlias + "." + currentTable.Schema.DB.QuoteField(schemaField.Relation.LocalLinkKey) + "=" + currentTable.TableAlias + "." + currentTable.Schema.DB.QuoteField(schemaField.Relation.LocalKey); currentJoin = null; } break; case CSSchemaRelationType.ManyToOne: { if (!isLast) { if (subExpression != null) // meaning we already encountered a *toMany relation { currentJoin = new CSJoin(schemaField.Relation, subExpression.Table.TableAlias); if (subExpression.Joins.Contains(currentJoin)) currentJoin = subExpression.Joins.GetExistingJoin(currentJoin); else subExpression.Joins.Add(currentJoin); } else { currentJoin = new CSJoin(schemaField.Relation, currentTable.TableAlias); if (parentQuery.Joins.Contains(currentJoin)) currentJoin = parentQuery.Joins.GetExistingJoin(currentJoin); else parentQuery.Joins.Add(currentJoin); } } } break; } if (!isLast) { if (currentJoin != null) currentTable = new CSTable(schemaField.Relation.ForeignSchema, currentJoin.RightAlias); else { if (subExpression != null) currentTable = new CSTable(schemaField.Relation.ForeignSchema, subExpression.Table.TableAlias); else currentTable = new CSTable(schemaField.Relation.ForeignSchema); } } else { fieldName = currentTable.Schema.DB.QuoteField(currentTable.TableAlias + "." + schemaField.Relation.LocalKey); } } else { fieldName = currentTable.Schema.DB.QuoteField(currentTable.TableAlias + "." + schemaField.MappedColumn.Name); } } if (subExpression != null) { subExpression.FieldName = fieldName; return subExpression; } else { //if (fieldName != null) return fieldName; } }