<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace SqlKata.Compilers
{
    public partial class Compiler : AbstractCompiler
    {
        private string[] selectComponents = new string[] {
            "aggregate",
            "columns",
            "from",
            "joins",
            "wheres",
            "groups",
            "havings",
            "orders",
            "limit",
            "offset",
            "unions",
            "lock",
        };

        public Compiler()
        {
            Inflector = new Inflector();
        }

        public SqlResult Compile(Query query)
        {
            query = OnBeforeCompile(query);
            var sql = CompileSelect(query);
            sql = OnAfterCompile(sql, query.Bindings);
            return new SqlResult(sql, query.Bindings);
        }

        public virtual Query OnBeforeCompile(Query query)
        {
            // Transfrom deep join expressions to regular join

            var deepJoins = query.Get<AbstractJoin>("join").OfType<DeepJoin>().ToList();

            foreach (var join in deepJoins)
            {
                TransfromDeepJoin(query, join);

                // Remove it from the query, since it's now converted
                query.Clauses.Remove(join);
            }

            return query;
        }

        public virtual string OnAfterCompile(string sql, List<object> bindings)
        {
            return sql;
        }

        public virtual Query TransfromDeepJoin(Query query, DeepJoin join)
        {
            var exp = join.Expression;

            var tokens = exp.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            if (!tokens.Any())
            {
                return query;
            }


            var from = query.GetOne<AbstractFrom>("from");

            if (from == null)
            {
                return query;
            }

            string tableOrAlias = from.Alias;

            if (string.IsNullOrEmpty(tableOrAlias))
            {
                throw new InvalidOperationException("No table or alias found for the main query, This information is needed in order to generate a Deep Join");
            }

            for (var i = 0; i < tokens.Length; i++)
            {
                var source = i == 0 ? tableOrAlias : tokens[i - 1];
                var target = tokens[i];

                string sourceKey;
                string targetKey;

                if (join.SourceKeyGenerator != null)
                {
                    // developer wants to use the lambda overloaded method then
                    sourceKey = join.SourceKeyGenerator.Invoke(target);
                    targetKey = join.TargetKeyGenerator?.Invoke(target) ?? "Id";
                }
                else
                {
                    sourceKey = Singular(target) + join.SourceKeySuffix;
                    targetKey = join.TargetKey;
                }

                query.Join(target, $"{source}.{sourceKey}", $"{target}.{targetKey}", "=", join.Type);
            }

            return query;
        }

        public virtual string CompileSelect(Query query)
        {
            if (!query.Has("select"))
            {
                query.Select("*");
            }

            var results = CompileComponents(query);

            return JoinComponents(results, "select");
        }

        protected List<string> CompileComponents(Query query)
        {
            var result = (new List<string>
            {
                this.CompileAggregate(query),
                this.CompileColumns(query),
                this.CompileFrom(query),
                this.CompileJoins(query),
                this.CompileWheres(query),
                this.CompileGroups(query),
                this.CompileHavings(query),
                this.CompileOrders(query),
                this.CompileLimit(query),
                this.CompileOffset(query),
                this.CompileUnions(query),
                this.CompileLock(query),
            })<commit_msg>replace deepjoin with basjoin inplace<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace SqlKata.Compilers
{
    public partial class Compiler : AbstractCompiler
    {
        private string[] selectComponents = new string[] {
            "aggregate",
            "columns",
            "from",
            "joins",
            "wheres",
            "groups",
            "havings",
            "orders",
            "limit",
            "offset",
            "unions",
            "lock",
        };

        public Compiler()
        {
            Inflector = new Inflector();
        }

        public SqlResult Compile(Query query)
        {
            query = OnBeforeCompile(query);
            var sql = CompileSelect(query);
            sql = OnAfterCompile(sql, query.Bindings);
            return new SqlResult(sql, query.Bindings);
        }

        public virtual Query OnBeforeCompile(Query query)
        {
            // Transfrom deep join expressions to regular join

            var deepJoins = query.Get<AbstractJoin>("join").OfType<DeepJoin>().ToList();

            foreach (var deepJoin in deepJoins)
            {
                var index = query.Clauses.IndexOf(deepJoin);

                query.Clauses.Remove(deepJoin);
                foreach (var join in TransfromDeepJoin(query, deepJoin))
                {
                    query.Clauses.Insert(index, join);
                    index++;
                }
            }

            return query;
        }

        public virtual string OnAfterCompile(string sql, List<object> bindings)
        {
            return sql;
        }

        public virtual IEnumerable<BaseJoin> TransfromDeepJoin(Query query, DeepJoin join)
        {
            var exp = join.Expression;

            var tokens = exp.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            if (!tokens.Any())
            {
                yield break;
            }


            var from = query.GetOne<AbstractFrom>("from");

            if (from == null)
            {
                yield break;
            }

            string tableOrAlias = from.Alias;

            if (string.IsNullOrEmpty(tableOrAlias))
            {
                throw new InvalidOperationException("No table or alias found for the main query, This information is needed in order to generate a Deep Join");
            }

            for (var i = 0; i < tokens.Length; i++)
            {
                var source = i == 0 ? tableOrAlias : tokens[i - 1];
                var target = tokens[i];

                string sourceKey;
                string targetKey;

                if (join.SourceKeyGenerator != null)
                {
                    // developer wants to use the lambda overloaded method then
                    sourceKey = join.SourceKeyGenerator.Invoke(target);
                    targetKey = join.TargetKeyGenerator?.Invoke(target) ?? "Id";
                }
                else
                {
                    sourceKey = Singular(target) + join.SourceKeySuffix;
                    targetKey = join.TargetKey;
                }

                // yield query.Join(target, $"{source}.{sourceKey}", $"{target}.{targetKey}", "=", join.Type);
                yield return new BaseJoin
                {
                    Component = "join",
                    Join = new Join().AsType(join.Type).JoinWith(target).On
                    ($"{source}.{sourceKey}", $"{target}.{targetKey}", "=")
                };
            }

            // return query;
        }

        public virtual string CompileSelect(Query query)
        {
            if (!query.Has("select"))
            {
                query.Select("*");
            }

            var results = CompileComponents(query);

            return JoinComponents(results, "select");
        }

        protected List<string> CompileComponents(Query query)
        {
            var result = (new List<string>
            {
                this.CompileAggregate(query),
                this.CompileColumns(query),
                this.CompileFrom(query),
                this.CompileJoins(query),
                this.CompileWheres(query),
                this.CompileGroups(query),
                this.CompileHavings(query),
                this.CompileOrders(query),
                this.CompileLimit(query),
                this.CompileOffset(query),
                this.CompileUnions(query),
                this.CompileLock(query),
            })
{'fraction_non_alphanumeric': 0.09581459702525078, 'fraction_numerical': 0.0006918021445866483, 'mean_word_length': 1.3525901817195551, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 16, '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': '5906553', 'n_tokens_mistral': 2189, 'n_tokens_neox': 2025, 'n_words': 483}