<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using NPoco;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Scoping;
using static Umbraco.Core.Persistence.NPocoSqlExtensions.Statics;

namespace Umbraco.Core.Persistence.Repositories.Implement
{
    // fixme - use sql templates everywhere!

    /// <summary>
    /// Represents the EntityRepository used to query entity objects.
    /// </summary>
    /// <remarks>
    /// <para>Limited to objects that have a corresponding node (in umbracoNode table).</para>
    /// <para>Returns <see cref="IEntitySlim"/> objects, i.e. lightweight representation of entities.</para>
    /// </remarks>
    internal class EntityRepository : IEntityRepository
    {
        private readonly IScopeAccessor _scopeAccessor;
        private readonly ILanguageRepository _langRepository;

        public EntityRepository(IScopeAccessor scopeAccessor, ILanguageRepository langRepository)
        {
            _scopeAccessor = scopeAccessor;
            _langRepository = langRepository;
        }

        protected IUmbracoDatabase Database => _scopeAccessor.AmbientScope.Database;
        protected Sql<ISqlContext> Sql() => _scopeAccessor.AmbientScope.SqlContext.Sql();

        #region Repository

        // get a page of entities
        public IEnumerable<IEntitySlim> GetPagedResultsByQuery(IQuery<IUmbracoEntity> query, Guid objectType, long pageIndex, int pageSize, out long totalRecords,
            string orderBy, Direction orderDirection, IQuery<IUmbracoEntity> filter = null)
        {
            var isContent = objectType == Constants.ObjectTypes.Document || objectType == Constants.ObjectTypes.DocumentBlueprint;
            var isMedia = objectType == Constants.ObjectTypes.Media;

            var sql = GetBaseWhere(isContent, isMedia, false, x =>
            {
                if (filter == null) return;
                foreach (var filterClause in filter.GetWhereClauses())
                    x.Where(filterClause.Item1, filterClause.Item2);
            }, objectType);

            var translator = new SqlTranslator<IUmbracoEntity>(sql, query);
            sql = translator.Translate();
            sql = AddGroupBy(isContent, isMedia, sql);
            sql = sql.OrderBy<NodeDto>(x => x.NodeId);

            //IEnumerable<IUmbracoEntity> result;
            //
            //if (isMedia)
            //{
            //    //Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
            //    var pagedResult = UnitOfWork.Database.Page<dynamic>(pageIndex + 1, pageSize, pagedSql);

            //    var ids = pagedResult.Items.Select(x => (int)x.id).InGroupsOf(2000);
            //    var entities = pagedResult.Items.Select(BuildEntityFromDynamic).Cast<IUmbracoEntity>().ToList();

            //    //Now we need to merge in the property data since we need paging and we can't do this the way that the big media query was working before
            //    foreach (var idGroup in ids)
            //    {
            //        var propSql = GetPropertySql(Constants.ObjectTypes.Media)
            //            .WhereIn<NodeDto>(x => x.NodeId, idGroup)
            //            .OrderBy<NodeDto>(x => x.NodeId);

            //        //This does NOT fetch all data into memory in a list, this will read
            //        // over the records as a data reader, this is much better for performance and memory,
            //        // but it means that during the reading of this data set, nothing else can be read
            //        // from SQL server otherwise we'll get an exception.
            //        var allPropertyData = UnitOfWork.Database.Query<dynamic>(propSql);

            //        //keep track of the current property data item being enumerated<commit_msg>fixes order by on list view<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using NPoco;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Scoping;
using static Umbraco.Core.Persistence.NPocoSqlExtensions.Statics;

namespace Umbraco.Core.Persistence.Repositories.Implement
{
    // fixme - use sql templates everywhere!

    /// <summary>
    /// Represents the EntityRepository used to query entity objects.
    /// </summary>
    /// <remarks>
    /// <para>Limited to objects that have a corresponding node (in umbracoNode table).</para>
    /// <para>Returns <see cref="IEntitySlim"/> objects, i.e. lightweight representation of entities.</para>
    /// </remarks>
    internal class EntityRepository : IEntityRepository
    {
        private readonly IScopeAccessor _scopeAccessor;
        private readonly ILanguageRepository _langRepository;

        public EntityRepository(IScopeAccessor scopeAccessor, ILanguageRepository langRepository)
        {
            _scopeAccessor = scopeAccessor;
            _langRepository = langRepository;
        }

        protected IUmbracoDatabase Database => _scopeAccessor.AmbientScope.Database;
        protected Sql<ISqlContext> Sql() => _scopeAccessor.AmbientScope.SqlContext.Sql();

        #region Repository

        // get a page of entities
        public IEnumerable<IEntitySlim> GetPagedResultsByQuery(IQuery<IUmbracoEntity> query, Guid objectType, long pageIndex, int pageSize, out long totalRecords,
            string orderBy, Direction orderDirection, IQuery<IUmbracoEntity> filter = null)
        {
            var isContent = objectType == Constants.ObjectTypes.Document || objectType == Constants.ObjectTypes.DocumentBlueprint;
            var isMedia = objectType == Constants.ObjectTypes.Media;

            var sql = GetBaseWhere(isContent, isMedia, false, x =>
            {
                if (filter == null) return;
                foreach (var filterClause in filter.GetWhereClauses())
                    x.Where(filterClause.Item1, filterClause.Item2);
            }, objectType);

            var translator = new SqlTranslator<IUmbracoEntity>(sql, query);
            sql = translator.Translate();
            sql = AddGroupBy(isContent, isMedia, sql);
            //fixme - we should be able to do sql = sql.OrderBy(x => Alias(x.NodeId, "NodeId")); but we can't because the OrderBy extension don't support Alias currently
            sql = sql.OrderBy("NodeId");

            //IEnumerable<IUmbracoEntity> result;
            //
            //if (isMedia)
            //{
            //    //Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
            //    var pagedResult = UnitOfWork.Database.Page<dynamic>(pageIndex + 1, pageSize, pagedSql);

            //    var ids = pagedResult.Items.Select(x => (int)x.id).InGroupsOf(2000);
            //    var entities = pagedResult.Items.Select(BuildEntityFromDynamic).Cast<IUmbracoEntity>().ToList();

            //    //Now we need to merge in the property data since we need paging and we can't do this the way that the big media query was working before
            //    foreach (var idGroup in ids)
            //    {
            //        var propSql = GetPropertySql(Constants.ObjectTypes.Media)
            //            .WhereIn<NodeDto>(x => x.NodeId, idGroup)
            //            .OrderBy<NodeDto>(x => x.NodeId);

            //        //This does NOT fetch all data into memory in a list, this will read
            //        // over the records as a data reader, this is much better for performance and memory,
            //        // but it means that during the reading of this data set, nothing else can be read
            //        // from SQL server otherwise we'll get an exception.
            //        var allPropertyData = UnitOfWork.Database.Query<dynamic>(propSql);

            //        //keep track of the current property data item being enumerated
{'fraction_non_alphanumeric': 0.09202827888834715, 'fraction_numerical': 0.0017064846416382253, 'mean_word_length': 2.3696098562628336, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 58, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6616184', 'n_tokens_mistral': 2166, 'n_tokens_neox': 2114, 'n_words': 635}