Esempio n. 1
0
        private void AddSchemaColumn(string outputColumn, string sourceColumn, NodeSchema schema, INodeSchema sourceSchema)
        {
            if (!sourceSchema.ContainsColumn(sourceColumn, out var normalized))
            {
                return;
            }

            var mapped = $"{Alias}.{outputColumn}";

            schema.Schema[mapped] = sourceSchema.Schema[normalized];

            if (normalized == sourceSchema.PrimaryKey)
            {
                schema.PrimaryKey = mapped;
            }

            if (!schema.Aliases.TryGetValue(outputColumn, out var aliases))
            {
                aliases = new List <string>();
                schema.Aliases[outputColumn] = aliases;
            }

            aliases.Add(mapped);

            var sorted = sourceSchema.SortOrder.Contains(sourceColumn, StringComparer.OrdinalIgnoreCase);

            if (sorted)
            {
                schema.SortOrder.Add(outputColumn);
            }
        }
Esempio n. 2
0
        private void AddSchemaAttribute(NodeSchema schema, string fullName, string simpleName, Type type, AttributeMetadata attrMetadata)
        {
            // Add the logical attribute
            AddSchemaAttribute(schema, fullName, simpleName, type);

            if (attrMetadata.IsPrimaryId == true)
            {
                _primaryKeyColumns[fullName] = attrMetadata.EntityLogicalName;
            }

            if (FetchXml.aggregate)
            {
                return;
            }

            // Add standard virtual attributes
            if (attrMetadata is EnumAttributeMetadata || attrMetadata is BooleanAttributeMetadata)
            {
                AddSchemaAttribute(schema, fullName + "name", attrMetadata.LogicalName + "name", typeof(SqlString));
            }

            if (attrMetadata is LookupAttributeMetadata lookup)
            {
                AddSchemaAttribute(schema, fullName + "name", attrMetadata.LogicalName + "name", typeof(SqlString));

                if (lookup.Targets?.Length > 1 && lookup.AttributeType != AttributeTypeCode.PartyList)
                {
                    AddSchemaAttribute(schema, fullName + "type", attrMetadata.LogicalName + "type", typeof(SqlString));
                }
            }
        }
Esempio n. 3
0
        public override INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes)
        {
            if (!dataSources.TryGetValue(DataSource, out var dataSource))
            {
                throw new NotSupportedQueryFragmentException("Missing datasource " + DataSource);
            }

            var fetchXmlString = FetchXmlString;

            if (_lastSchema != null && Alias == _lastSchemaAlias && fetchXmlString == _lastSchemaFetchXml)
            {
                return(_lastSchema);
            }

            _primaryKeyColumns = new Dictionary <string, string>();
            var schema = new NodeSchema();

            // Add each attribute from the main entity and recurse into link entities
            var entity = FetchXml.Items.OfType <FetchEntityType>().Single();
            var meta   = dataSource.Metadata[entity.name];

            if (!FetchXml.aggregate)
            {
                schema.PrimaryKey = $"{Alias}.{meta.PrimaryIdAttribute}";
            }

            AddSchemaAttributes(schema, dataSource.Metadata, entity.name, Alias, entity.Items);

            _lastSchema         = schema;
            _lastSchemaFetchXml = fetchXmlString;
            _lastSchemaAlias    = Alias;
            return(schema);
        }
Esempio n. 4
0
        public override INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes)
        {
            // Map the base names to the alias names
            var sourceSchema = Source.GetSchema(dataSources, parameterTypes);
            var schema       = new NodeSchema();

            foreach (var col in ColumnSet)
            {
                if (col.AllColumns)
                {
                    foreach (var sourceCol in sourceSchema.Schema)
                    {
                        if (col.SourceColumn != null && !sourceCol.Key.StartsWith(col.SourceColumn + "."))
                        {
                            continue;
                        }

                        var simpleName = sourceCol.Key.Split('.').Last();
                        var outputName = $"{Alias}.{simpleName}";

                        AddSchemaColumn(simpleName, sourceCol.Key, schema, sourceSchema);
                    }
                }
                else
                {
                    AddSchemaColumn(col.OutputColumn, col.SourceColumn, schema, sourceSchema);
                }
            }

            return(schema);
        }
Esempio n. 5
0
        public override INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes)
        {
            var schema       = new NodeSchema();
            var sourceSchema = Sources[0].GetSchema(dataSources, parameterTypes);

            foreach (var col in ColumnSet)
            {
                schema.Schema[col.OutputColumn] = sourceSchema.Schema[col.SourceColumns[0]];
            }

            return(schema);
        }
Esempio n. 6
0
        public override INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes)
        {
            // Copy the source schema and add in the additional computed columns
            var sourceSchema = Source.GetSchema(dataSources, parameterTypes);
            var schema       = new NodeSchema(sourceSchema);

            foreach (var calc in Columns)
            {
                schema.Schema[calc.Key] = calc.Value.GetType(sourceSchema, null, parameterTypes);
            }

            return(schema);
        }
Esempio n. 7
0
        /// <summary>
        /// Gets the records to perform the DML operation on
        /// </summary>
        /// <param name="org">The <see cref="IOrganizationService"/> to use to get the data</param>
        /// <param name="metadata">The <see cref="IAttributeMetadataCache"/> to use to get metadata</param>
        /// <param name="options"><see cref="IQueryExecutionOptions"/> to indicate how the query can be executed</param>
        /// <param name="parameterTypes">A mapping of parameter names to their related types</param>
        /// <param name="parameterValues">A mapping of parameter names to their current values</param>
        /// <param name="schema">The schema of the data source</param>
        /// <returns>The entities to perform the DML operation on</returns>
        protected List <Entity> GetDmlSourceEntities(IDictionary <string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary <string, Type> parameterTypes, IDictionary <string, object> parameterValues, out INodeSchema schema)
        {
            List <Entity> entities;

            if (Source is IDataExecutionPlanNode dataSource)
            {
                schema   = dataSource.GetSchema(dataSources, parameterTypes);
                entities = dataSource.Execute(dataSources, options, parameterTypes, parameterValues).ToList();
            }
            else if (Source is IDataSetExecutionPlanNode dataSetSource)
            {
                var dataTable = dataSetSource.Execute(dataSources, options, parameterTypes, parameterValues);

                // Store the values under the column index as well as name for compatibility with INSERT ... SELECT ...
                schema = new NodeSchema();

                for (var i = 0; i < dataTable.Columns.Count; i++)
                {
                    var col = dataTable.Columns[i];
                    ((NodeSchema)schema).Schema[col.ColumnName] = col.DataType;
                    ((NodeSchema)schema).Schema[i.ToString()]   = col.DataType;
                }

                entities = dataTable.Rows
                           .Cast <DataRow>()
                           .Select(row =>
                {
                    var entity = new Entity();

                    for (var i = 0; i < dataTable.Columns.Count; i++)
                    {
                        entity[dataTable.Columns[i].ColumnName] = row[i];
                        entity[i.ToString()] = row[i];
                    }

                    return(entity);
                })
                           .ToList();
            }
            else
            {
                throw new QueryExecutionException("Unexpected data source")
                      {
                          Node = this
                      };
            }

            return(entities);
        }
Esempio n. 8
0
        public override INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes)
        {
            var sourceSchema = Source.GetSchema(dataSources, parameterTypes);
            var schema       = new NodeSchema();

            foreach (var group in GroupBy)
            {
                var colName = group.GetColumnName();
                sourceSchema.ContainsColumn(colName, out var normalized);
                schema.Schema[normalized] = sourceSchema.Schema[normalized];

                foreach (var alias in sourceSchema.Aliases.Where(a => a.Value.Contains(normalized)))
                {
                    if (!schema.Aliases.TryGetValue(alias.Key, out var aliases))
                    {
                        aliases = new List <string>();
                        schema.Aliases[alias.Key] = aliases;
                    }

                    aliases.Add(normalized);
                }

                if (GroupBy.Count == 1)
                {
                    schema.PrimaryKey = normalized;
                }
            }

            foreach (var aggregate in Aggregates)
            {
                Type aggregateType;

                switch (aggregate.Value.AggregateType)
                {
                case AggregateType.Count:
                case AggregateType.CountStar:
                    aggregateType = typeof(SqlInt32);
                    break;

                default:
                    aggregateType = aggregate.Value.SqlExpression.GetType(sourceSchema, null, parameterTypes);
                    break;
                }

                schema.Schema[aggregate.Key] = aggregateType;
            }

            return(schema);
        }
Esempio n. 9
0
        public override INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes)
        {
            var schema = Source.GetSchema(dataSources, parameterTypes);

            // If this is a distinct list of one column we know the values in that column will be unique
            if (Columns.Count == 1)
            {
                schema = new NodeSchema(schema)
                {
                    PrimaryKey = Columns[0]
                }
            }
            ;

            return(schema);
        }
Esempio n. 10
0
        protected virtual INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes, bool includeSemiJoin)
        {
            var outerSchema = LeftSource.GetSchema(dataSources, parameterTypes);
            var innerSchema = GetRightSchema(dataSources, parameterTypes);

            var schema = new NodeSchema();

            if (JoinType == QualifiedJoinType.LeftOuter && SemiJoin)
            {
                schema.PrimaryKey = outerSchema.PrimaryKey;
            }

            foreach (var subSchema in new[] { outerSchema, innerSchema })
            {
                // Semi-join does not include data from the right source
                if (SemiJoin && subSchema == innerSchema && !includeSemiJoin)
                {
                    continue;
                }

                foreach (var column in subSchema.Schema)
                {
                    schema.Schema[column.Key] = column.Value;
                }

                foreach (var alias in subSchema.Aliases)
                {
                    if (!schema.Aliases.TryGetValue(alias.Key, out var aliasDetails))
                    {
                        aliasDetails = new List <string>();
                        schema.Aliases[alias.Key] = aliasDetails;
                    }

                    schema.Aliases[alias.Key].AddRange(alias.Value);
                }
            }

            foreach (var definedValue in DefinedValues)
            {
                schema.Schema[definedValue.Key] = innerSchema.Schema[definedValue.Value];
            }

            return(schema);
        }
Esempio n. 11
0
        private void AddSchemaAttribute(NodeSchema schema, string fullName, string simpleName, Type type)
        {
            schema.Schema[fullName] = type;

            if (simpleName == null)
            {
                return;
            }

            if (!schema.Aliases.TryGetValue(simpleName, out var simpleColumnNameAliases))
            {
                simpleColumnNameAliases    = new List <string>();
                schema.Aliases[simpleName] = simpleColumnNameAliases;
            }

            if (!simpleColumnNameAliases.Contains(fullName))
            {
                simpleColumnNameAliases.Add(fullName);
            }
        }
Esempio n. 12
0
        public override INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes)
        {
            var schema = new NodeSchema();

            foreach (var prop in _optionsetProps.Values)
            {
                schema.Schema[$"{Alias}.{prop.Name}"] = prop.Type;

                if (!schema.Aliases.TryGetValue(prop.Name, out var aliases))
                {
                    aliases = new List <string>();
                    schema.Aliases[prop.Name] = aliases;
                }

                aliases.Add($"{Alias}.{prop.Name}");
            }

            schema.PrimaryKey = $"{Alias}.{nameof(OptionSetMetadataBase.MetadataId)}";

            return(schema);
        }
Esempio n. 13
0
        public override INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes)
        {
            var schema = new NodeSchema(Source.GetSchema(dataSources, parameterTypes));

            schema.SortOrder.Clear();

            foreach (var sort in Sorts)
            {
                if (!(sort.Expression is ColumnReferenceExpression col))
                {
                    return(schema);
                }

                if (!schema.ContainsColumn(col.GetColumnName(), out var colName))
                {
                    return(schema);
                }

                schema.SortOrder.Add(colName);
            }

            return(schema);
        }
Esempio n. 14
0
        private void AddSchemaAttributes(NodeSchema schema, IAttributeMetadataCache metadata, string entityName, string alias, object[] items)
        {
            if (items == null && !ReturnFullSchema)
            {
                return;
            }

            var meta = metadata[entityName];

            if (ReturnFullSchema)
            {
                foreach (var attrMetadata in meta.Attributes)
                {
                    if (attrMetadata.IsValidForRead == false)
                    {
                        continue;
                    }

                    if (attrMetadata.AttributeOf != null)
                    {
                        continue;
                    }

                    var fullName = $"{alias}.{attrMetadata.LogicalName}";
                    var attrType = attrMetadata.GetAttributeSqlType();
                    AddSchemaAttribute(schema, fullName, attrMetadata.LogicalName, attrType, attrMetadata);
                }
            }

            if (items != null)
            {
                foreach (var attribute in items.OfType <FetchAttributeType>())
                {
                    var attrMetadata = meta.Attributes.Single(a => a.LogicalName == attribute.name);
                    var attrType     = attrMetadata.GetAttributeSqlType();

                    if (attribute.aggregateSpecified && (attribute.aggregate == Engine.FetchXml.AggregateType.count || attribute.aggregate == Engine.FetchXml.AggregateType.countcolumn) ||
                        attribute.dategroupingSpecified)
                    {
                        attrType = typeof(SqlInt32);
                    }

                    string fullName;
                    string attrAlias;

                    if (!String.IsNullOrEmpty(attribute.alias))
                    {
                        if (!FetchXml.aggregate || attribute.groupbySpecified && attribute.groupby == FetchBoolType.@true)
                        {
                            fullName  = $"{alias}.{attribute.alias}";
                            attrAlias = attribute.alias;
                        }
                        else
                        {
                            fullName  = attribute.alias;
                            attrAlias = null;
                        }
                    }
                    else
                    {
                        fullName  = $"{alias}.{attribute.name}";
                        attrAlias = attribute.name;
                    }

                    AddSchemaAttribute(schema, fullName, attrAlias, attrType, attrMetadata);
                }

                if (items.OfType <allattributes>().Any())
                {
                    foreach (var attrMetadata in meta.Attributes)
                    {
                        if (attrMetadata.IsValidForRead == false)
                        {
                            continue;
                        }

                        if (attrMetadata.AttributeOf != null)
                        {
                            continue;
                        }

                        var attrType = attrMetadata.GetAttributeSqlType();
                        var attrName = attrMetadata.LogicalName;
                        var fullName = $"{alias}.{attrName}";

                        AddSchemaAttribute(schema, fullName, attrName, attrType, attrMetadata);
                    }
                }

                foreach (var sort in items.OfType <FetchOrderType>())
                {
                    string fullName;
                    string attributeName;

                    if (!String.IsNullOrEmpty(sort.alias))
                    {
                        var attribute = items.OfType <FetchAttributeType>().SingleOrDefault(a => a.alias.Equals(sort.alias, StringComparison.OrdinalIgnoreCase));

                        if (!FetchXml.aggregate || attribute != null && attribute.groupbySpecified && attribute.groupby == FetchBoolType.@true)
                        {
                            fullName = $"{alias}.{attribute.alias}";
                        }
                        else
                        {
                            fullName = attribute.alias;
                        }

                        attributeName = attribute.name;
                    }
                    else
                    {
                        fullName      = $"{alias}.{sort.attribute}";
                        attributeName = sort.attribute;
                    }

                    // Sorts applied to lookup or enum fields are actually performed on the associated ___name virtual attribute
                    var attrMeta = meta.Attributes.SingleOrDefault(a => a.LogicalName.Equals(attributeName, StringComparison.OrdinalIgnoreCase));

                    if (attrMeta is LookupAttributeMetadata || attrMeta is EnumAttributeMetadata || attrMeta is BooleanAttributeMetadata)
                    {
                        fullName += "name";
                    }

                    schema.SortOrder.Add(fullName);
                }

                foreach (var linkEntity in items.OfType <FetchLinkEntityType>())
                {
                    if (linkEntity.SemiJoin)
                    {
                        continue;
                    }

                    if (schema.PrimaryKey != null)
                    {
                        var childMeta = metadata[linkEntity.name];

                        if (linkEntity.from != childMeta.PrimaryIdAttribute)
                        {
                            if (linkEntity.linktype == "inner")
                            {
                                schema.PrimaryKey = $"{linkEntity.alias}.{childMeta.PrimaryIdAttribute}";
                            }
                            else
                            {
                                schema.PrimaryKey = null;
                            }
                        }
                    }

                    AddSchemaAttributes(schema, metadata, linkEntity.name, linkEntity.alias, linkEntity.Items);
                }
            }
        }
Esempio n. 15
0
        public override INodeSchema GetSchema(IDictionary <string, DataSource> dataSources, IDictionary <string, Type> parameterTypes)
        {
            var schema     = new NodeSchema();
            var childCount = 0;

            if (MetadataSource.HasFlag(MetadataSource.Entity))
            {
                var entityProps = (IEnumerable <MetadataProperty>)_entityProps.Values;

                if (Query.Properties != null)
                {
                    entityProps = entityProps.Where(p => Query.Properties.AllProperties || Query.Properties.PropertyNames.Contains(p.PropertyName, StringComparer.OrdinalIgnoreCase));
                }

                foreach (var prop in entityProps)
                {
                    schema.Schema[$"{EntityAlias}.{prop.SqlName}"] = prop.Type;

                    if (!schema.Aliases.TryGetValue(prop.SqlName, out var aliases))
                    {
                        aliases = new List <string>();
                        schema.Aliases[prop.SqlName] = aliases;
                    }

                    aliases.Add($"{EntityAlias}.{prop.SqlName}");
                }

                schema.PrimaryKey = $"{EntityAlias}.{nameof(EntityMetadata.MetadataId)}";
            }

            if (MetadataSource.HasFlag(MetadataSource.Attribute))
            {
                var attributeProps = (IEnumerable <AttributeProperty>)_attributeProps.Values;

                if (Query.AttributeQuery?.Properties != null)
                {
                    attributeProps = attributeProps.Where(p => Query.AttributeQuery.Properties.AllProperties || Query.AttributeQuery.Properties.PropertyNames.Contains(p.PropertyName, StringComparer.OrdinalIgnoreCase));
                }

                foreach (var prop in attributeProps)
                {
                    schema.Schema[$"{AttributeAlias}.{prop.SqlName}"] = prop.Type;

                    if (!schema.Aliases.TryGetValue(prop.SqlName, out var aliases))
                    {
                        aliases = new List <string>();
                        schema.Aliases[prop.SqlName] = aliases;
                    }

                    aliases.Add($"{AttributeAlias}.{prop.SqlName}");
                }

                schema.PrimaryKey = $"{AttributeAlias}.{nameof(AttributeMetadata.MetadataId)}";
                childCount++;
            }

            if (MetadataSource.HasFlag(MetadataSource.OneToManyRelationship))
            {
                var relationshipProps = (IEnumerable <MetadataProperty>)_oneToManyRelationshipProps.Values;

                if (Query.RelationshipQuery?.Properties != null)
                {
                    relationshipProps = relationshipProps.Where(p => Query.RelationshipQuery.Properties.AllProperties || Query.RelationshipQuery.Properties.PropertyNames.Contains(p.PropertyName, StringComparer.OrdinalIgnoreCase));
                }

                foreach (var prop in relationshipProps)
                {
                    schema.Schema[$"{OneToManyRelationshipAlias}.{prop.SqlName}"] = prop.Type;

                    if (!schema.Aliases.TryGetValue(prop.SqlName, out var aliases))
                    {
                        aliases = new List <string>();
                        schema.Aliases[prop.SqlName] = aliases;
                    }

                    aliases.Add($"{OneToManyRelationshipAlias}.{prop.SqlName}");
                }

                schema.PrimaryKey = $"{OneToManyRelationshipAlias}.{nameof(RelationshipMetadataBase.MetadataId)}";
                childCount++;
            }

            if (MetadataSource.HasFlag(MetadataSource.ManyToOneRelationship))
            {
                var relationshipProps = (IEnumerable <MetadataProperty>)_oneToManyRelationshipProps.Values;

                if (Query.RelationshipQuery?.Properties != null)
                {
                    relationshipProps = relationshipProps.Where(p => Query.RelationshipQuery.Properties.AllProperties || Query.RelationshipQuery.Properties.PropertyNames.Contains(p.PropertyName, StringComparer.OrdinalIgnoreCase));
                }

                foreach (var prop in relationshipProps)
                {
                    schema.Schema[$"{ManyToOneRelationshipAlias}.{prop.SqlName}"] = prop.Type;

                    if (!schema.Aliases.TryGetValue(prop.SqlName, out var aliases))
                    {
                        aliases = new List <string>();
                        schema.Aliases[prop.SqlName] = aliases;
                    }

                    aliases.Add($"{ManyToOneRelationshipAlias}.{prop.SqlName}");
                }

                schema.PrimaryKey = $"{ManyToOneRelationshipAlias}.{nameof(RelationshipMetadataBase.MetadataId)}";
                childCount++;
            }

            if (MetadataSource.HasFlag(MetadataSource.ManyToManyRelationship))
            {
                var relationshipProps = (IEnumerable <MetadataProperty>)_manyToManyRelationshipProps.Values;

                if (Query.RelationshipQuery?.Properties != null)
                {
                    relationshipProps = relationshipProps.Where(p => Query.RelationshipQuery.Properties.AllProperties || Query.RelationshipQuery.Properties.PropertyNames.Contains(p.PropertyName, StringComparer.OrdinalIgnoreCase));
                }

                foreach (var prop in relationshipProps)
                {
                    schema.Schema[$"{ManyToManyRelationshipAlias}.{prop.SqlName}"] = prop.Type;

                    if (!schema.Aliases.TryGetValue(prop.SqlName, out var aliases))
                    {
                        aliases = new List <string>();
                        schema.Aliases[prop.SqlName] = aliases;
                    }

                    aliases.Add($"{ManyToManyRelationshipAlias}.{prop.SqlName}");
                }

                schema.PrimaryKey = $"{ManyToManyRelationshipAlias}.{nameof(RelationshipMetadataBase.MetadataId)}";
                childCount++;
            }

            if (childCount > 1)
            {
                schema.PrimaryKey = null;
            }

            return(schema);
        }