Example #1
0
        private async Task ProcessIncludes(List <IEntity> results, CancellationToken ct)
        {
            if (!Includes.Any())
            {
                return;
            }

            //TODO: optimize / parallel processing
            foreach (var propertyDefinition in Includes)
            {
                var targetEntityDefinition =
                    (IEntityDefinition)propertyDefinition.PropertyType.GetTargetValueType(propertyDefinition);

                var foreignIds = results
                                 .Select(x => x[propertyDefinition.Name])
                                 .Where(x => x != null)
                                 .Cast <IEntity>()
                                 .Select(x => _repository.GetDocumentId(targetEntityDefinition, x.Id))
                                 .Distinct();

                var foreignQuery = new DocumentDbQuery(_repository, targetEntityDefinition)
                                   .Add(Criterion.In(MetaConstants.IdProperty, foreignIds.Cast <object>().ToArray()));
                var foreignEntities = (await foreignQuery.ToEnumerable <IEntity>(ct)).ToDictionary(x => x.Id);

                results.ForEach(x =>
                {
                    var foreignId = ((IEntity)x[propertyDefinition.Name])?.Id;
                    if (foreignId != null && foreignEntities.ContainsKey(foreignId))
                    {
                        x[propertyDefinition.Name] = foreignEntities[foreignId];
                    }
                });
            }
        }
Example #2
0
        private async Task <SqlQuerySpec> BuildQuerySpec(DocumentDbQuery query, CancellationToken ct)
        {
            if (!query.FullQuery.IsNullOrEmpty())
            {
                return(new SqlQuerySpec(query.FullQuery));
            }

            var parameters = new SqlParameterCollection();

            return(new SqlQuerySpec($"SELECT {BuildSelect(query)} FROM ROOT {await BuildWhere(query, parameters, ct)} {BuildOrder(query)}", parameters));
        }
Example #3
0
        private static string BuildSelect(DocumentDbQuery query)
        {
            if (query.Projection == null)
            {
                return("VALUE ROOT");
            }

            if (query.Projection.PropertyNames.Safe().Any())
            {
                return(string.Join(", ", query.Projection.PropertyNames.Select(x => $"ROOT.{x}")));
            }

            throw new NotSupportedException();
        }
Example #4
0
        private static string BuildOrder(DocumentDbQuery query)
        {
            if (!query.Orders.Any())
            {
                return(null);
            }

            if (query.Orders.Count > 1)
            {
                throw new QueryException(query, "Document db does not support multiple order by.");
            }

            var order = query.Orders[0];

            return($"ORDER BY ROOT.{order.PropertyName} {(order.Ascending ? "ASC" : "DESC")}");
        }
Example #5
0
        private static async Task <string> BuildWhere(DocumentDbQuery query, SqlParameterCollection parameters, CancellationToken ct)
        {
            var joins = new List <string>();

            var whereConditions = new List <string>
            {
                "ROOT." + DocumentDbConstants.EntityDefinitionProperty + " = @" + DocumentDbConstants.EntityDefinitionProperty
            };

            parameters.Add(new SqlParameter("@" + DocumentDbConstants.EntityDefinitionProperty, query.EntityDefinition.FullName));

            foreach (var criterion in query.Criterions)
            {
                string remaining;
                var    leading = criterion.PropertyName.SplitFirst('.', out remaining);

                var propertyDefinition = query.EntityDefinition.Properties.SafeGet(leading);
                if (propertyDefinition == null)
                {
                    throw new QueryException(query, $"Unable to find a property named {leading} on {query.EntityDefinition}");
                }

                var criteria = $"ROOT.{criterion.PropertyName}";
                if (propertyDefinition.PropertyType is ArrayValueType)
                {
                    var prefix = GetPrefixName(propertyDefinition.Name);
                    joins.Add($" JOIN {prefix} IN ROOT.{propertyDefinition.Name}");
                    criteria = $"{prefix}.{remaining}";
                }

                switch (criterion.Operator)
                {
                case Operators.Eq:
                    var parameterName = GetParameterName(criterion.PropertyName);
                    whereConditions.Add($"{criteria} = @{parameterName}");
                    parameters.Add(new SqlParameter($"@{parameterName}", criterion.Value));
                    break;

                case Operators.In:
                    whereConditions.Add($"{criteria} IN ({string.Join(", ", GetInValues(criterion.Value))})");
                    break;

                default:
                    throw new QueryException(query, $"Unsupported operator {criterion.Operator}.");
                }
            }

            foreach (var subQuery in query.SubQueries)
            {
                if (subQuery.Value.IsIdQuery)
                {
                    whereConditions.Add($"ROOT.{subQuery.Key}.{MetaConstants.IdProperty} = @{subQuery.Key}");
                    parameters.Add(new SqlParameter($"@{subQuery.Key}", ((DocumentDbQuery)subQuery.Value).Criterions[0].Value));
                }
                else
                {
                    // We actually need to run the subquery at that point
                    var subEntities    = await((DocumentDbQuery)subQuery.Value).ToEnumerable <IEntity>(ct);
                    var subEntitiesIds = subEntities.Safe().Select(x => x.Id);
                    whereConditions.Add(
                        $"ROOT.{subQuery.Key}.{MetaConstants.IdProperty} IN ({string.Join(", ", GetInValues(subEntitiesIds))})");
                }
            }

            return($"{string.Join(" ", joins)} WHERE {string.Join(" AND ", whereConditions)}");
        }