/// <summary> /// Used by logic planner to update the list of ReferencedFields /// </summary> internal virtual void PropagateReferencedPropertiesForEntityFields() { // lift the referenced fields from the next layer of operators back to this one's output entity fields var referredFieldsInDownstreamOps = OutOperators.SelectMany(op => op.InputSchema) .Where(f => f is EntityField) .Cast <EntityField>() .GroupBy(f => f.FieldAlias) .ToDictionary(kv => kv.Key, kv => kv.SelectMany(fn => fn.ReferencedFieldAliases).Distinct().ToList()); foreach (var field in OutputSchema.Where(f => f is EntityField).Cast <EntityField>()) { Debug.Assert(referredFieldsInDownstreamOps.ContainsKey(field.FieldAlias)); field.AddReferenceFieldNames(referredFieldsInDownstreamOps[field.FieldAlias]); } // lift the referenced fields in the entity fields from output to input schema of this operator, if // applicable if ((InputSchema?.Count ?? 0) > 0) { // handle entity name renamed cases by creating a map from field alias before projection to after // projection var aliasMap = new Dictionary <String, String>(); if (this is ProjectionOperator) { var aliasMap1 = (this as ProjectionOperator).ProjectionMap .Where(u => OutputSchema.Where(n => n is EntityField).Any(k => k.FieldAlias == u.Key)); aliasMap = aliasMap1?.ToDictionary(n => n.Value.GetChildrenQueryExpressionType <QueryExpressionProperty>().First().VariableName, n => n.Key); } else { // create a dummy alias map ( A -> A, B -> B; not alias name modified) for non-projection operator aliasMap = OutputSchema.Where(n => n is EntityField).ToDictionary(n => n.FieldAlias, n => n.FieldAlias); } foreach (var field in InputSchema.Where(f => f is EntityField).Cast <EntityField>()) { var mappedAlias = (aliasMap.ContainsKey(field.FieldAlias) ?aliasMap[field.FieldAlias]:null); if (mappedAlias != null && referredFieldsInDownstreamOps.ContainsKey(mappedAlias)) { field.AddReferenceFieldNames(referredFieldsInDownstreamOps[mappedAlias]); } } var referredFieldsForUpstream = InputSchema .Where(f => f is EntityField).Cast <EntityField>() .ToDictionary(kv => kv.FieldAlias, kv => kv); // Some operators has additional fields may get referenced even they are not in output schema // Such as in WHERE or ORDER BY // Child logical operator class implement this and does the appending AppendReferencedProperties(referredFieldsForUpstream); } }
protected override Delegate[] CreateGetters(DataViewRow input, Func <int, bool> active, out Action disp) { var bindings = GetBindings(); IEnumerable <DataViewSchema.Column> inputColumns; Func <int, bool> predicateMapper; IEnumerable <DataViewSchema.Column> activeColumns = OutputSchema.Where(col => active(col.Index)); GetActive(bindings, activeColumns, out inputColumns, out predicateMapper); var output = bindings.RowMapper.GetRow(input, predicateMapper); Func <int, bool> activeInfos = iinfo => active(bindings.MapIinfoToCol(iinfo)); disp = output.Dispose; return(GetGetters(output, activeInfos)); }