<commit_before>﻿
/**
 * Figlotech.BDados.Builders.MySqlQueryGenerator
 * MySQL implementation for IQueryGEnerator, used by the MySqlDataAccessor
 * For generating SQL Queries.
 * 
 * @Author: <NAME>
 * August/2014
 * 
**/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Figlotech.BDados.DataAccessAbstractions;
using Figlotech.Core.Interfaces;
using System.Reflection;
using System.Linq.Expressions;
using Figlotech.BDados.Helpers;
using Figlotech.BDados.DataAccessAbstractions.Attributes;
using Figlotech.Core;
using System.Text.RegularExpressions;
using Figlotech.BDados.Builders;
using Figlotech.Core.Helpers;
using System.Diagnostics;

namespace Figlotech.BDados.MySqlDataAccessor {
    public class MySqlQueryGenerator : IQueryGenerator {

        public IQueryBuilder GenerateInsertQuery(IDataObject inputObject) {
            QueryBuilder query = new QbFmt($"INSERT INTO {inputObject.GetType().Name}");
            query.Append("(");
            query.Append(GenerateFieldsString(inputObject.GetType(), true));
            query.Append(")");
            query.Append("VALUES (");
            var members = GetMembers(inputObject.GetType());
            members.RemoveAll(m => m.GetCustomAttribute<PrimaryKeyAttribute>() != null);
            for (int i = 0; i < members.Count; i++) {
                var val = ReflectionTool.GetMemberValue(members[i], inputObject);
                if (val == null) {
                    var pc = members[i].GetCustomAttribute<PreemptiveCounter>();
                    var ic = members[i].GetCustomAttribute<IncrementalCounter>();

                    if (pc != null) {
                        query.Append(pc.OnInsertSubQuery(inputObject.GetType(), members[i]));
                    } else
                    if (ic != null) {
                        query.Append(ic.OnInsertSubQuery(inputObject.GetType(), members[i]));
                    } else {
                        query.Append($"@{members[i].Name}_{i + 1}", val);
                    }
                } else {
                    query.Append($"@{members[i].Name}_{i + 1}", val);
                }

                if (i < members.Count - 1) {
                    query.Append(",");
                }
            }
            query.Append(")");
            //query.Append("ON DUPLICATE KEY UPDATE ");
            //var Fields = GetMembers(inputObject.GetType()).Where(field =>
            //    field.GetCustomAttribute(typeof(PrimaryKeyAttribute)) == null &&
            //    field.GetCustomAttribute(typeof(ReliableIdAttribute)) == null
            //).ToList();
            //for (int i = 0; i < Fields.Count; ++i) {
            //    query.Append(String.Format("{0} = VALUES({0})", Fields[i].Name));
            //    if (i < Fields.Count - 1) {
            //        query.Append(",");
            //    }
            //}
            return query;
        }

        public IQueryBuilder GetCreationCommand(Type t) {
            String objectName = t.Name;

            var members = ReflectionTool.FieldsAndPropertiesOf(t);
            members.RemoveAll(
                (m) => m?.GetCustomAttribute<FieldAttribute>() == null);
            if (objectName == null || objectName.Length == 0)
                return null;
            QueryBuilder CreateTable = new QbFmt($"CREATE TABLE IF NOT EXISTS {objectName} (\n");
            for (int i = 0; i < members.Length; i++) {
                var info = members[i].GetCustomAttribute<FieldAttribute>();
                CreateTable.Append(Fi.Tech.GetColumnDefinition(members[i], info));
                CreateTable.Append(" ");
                CreateTable.Append(info.Options ?? "");
                if (i != members.Length - 1) {
                    CreateTable.Append(", \n");
                }
            }
            CreateTable.Append(" );");
            return CreateTable;
        }

        public IQueryBuilder GenerateCallProcedure(string name, object[] args) {
            QueryBuilder query = new QbFmt($"CALL {name}");
            for (int i = 0; i < args.Length; i++) {
                if (i == 0) {
                    query.Append("(");
                }
                query.Append($"@{i + 1}", args[i]);
                if (i < args.Length - 1)
                    query.Append(",");
                if (i == args.Length - 1) {
                    query.Append(")");
                }
            }
            return query;
        }

        private bool RelatesWithMain(string a) {
            var retv = (a.StartsWith("a.") || a.Contains("=a."));
            return retv;
        }

        static Dictionary<JoinDefinition, QueryBuilder> AutoJoinCache = new Dictionary<JoinDefinition, QueryBuilder>();
        public IQueryBuilder GenerateJoinQuery(JoinDefinition inputJoin, IQueryBuilder conditions, int? skip = null, int? take = null, MemberInfo orderingMember = null, OrderingType otype = OrderingType.Asc, IQueryBuilder rootConditions = null) {
            if (rootConditions == null)
                rootConditions = new QbFmt("true");
            if (inputJoin.Joins.Count < 1)
                throw new BDadosException("This join needs 1 or more tables.");

            List<Type> tables = (from a in inputJoin.Joins select a.ValueObject).ToList();
            List<String> tableNames = (from a in inputJoin.Joins select a.ValueObject.Name).ToList();
            List<String> prefixes = (from a in inputJoin.Joins select a.Prefix).ToList();
            List<String> aliases = (from a in inputJoin.Joins select a.Alias).ToList();
            List<String> onclauses = (from a in inputJoin.Joins select a.Args).ToList();
            List<List<String>> columns = (from a in inputJoin.Joins select a.Columns).ToList();
            List<JoinType> joinTypes = (from a in inputJoin.Joins select a.Type).ToList();

            var isLinedAggregateJoin = false; // && conditions.GetCommandText() == rootConditions.GetCommandText() && conditions.GetParameters().SequenceEqual(rootConditions.GetParameters());

            QueryBuilder Query = new QueryBuilder();

            if(!AutoJoinCache.ContainsKey(inputJoin)) {
                // By caching this heavy process I might gain loads of performance
                // When redoing the same queries.
                QueryBuilder autoJoinMain = new QbFmt("SELECT sub.*\n");
                autoJoinMain.Append($"\t FROM (SELECT\n");
                for (int i = 0; i < tables.Count; i++) {
                    autoJoinMain.Append($"\t\t-- Table {tableNames[i]}\n");
                    var ridF = FiTechBDadosExtensions.RidColumnOf[tables[i]];
                    if (!columns[i].Any(c => c.ToUpper() == ridF.ToUpper()))
                        columns[i].Add(ridF);
                    var nonexcl = columns[i];
                    for (int j = 0; j < nonexcl.Count; j++) {
                        autoJoinMain.Append($"\t\t{prefixes[i]}.{nonexcl[j]} AS {prefixes[i]}_{nonexcl[j]}");
                        if (true || j < nonexcl.Count - 1 || i < tables.Count - 1) {
                            autoJoinMain.Append(",");
                        }
                        autoJoinMain.Append("\n");
                    }
                    autoJoinMain.Append("\n");
                }

                autoJoinMain.Append($"\t\t1 FROM (SELECT * FROM {tableNames[0]}");

                if (isLinedAggregateJoin) {
                    if (rootConditions != null) {
                        autoJoinMain.Append("WHERE ");
                        autoJoinMain.Append(rootConditions);
                    }
                    if (orderingMember != null) {
                        autoJoinMain.Append($"ORDER BY {orderingMember.Name} {otype.ToString().ToUpper()}");
                    }
                    if (skip != null || take != null) {
                        autoJoinMain.Append("LIMIT ");
                        autoJoinMain.Append(
                            skip != null ? $"{skip},{take ?? Int32.MaxValue}" : $"{take ?? Int32.MaxValue}"
                        );
                    }
                    autoJoinMain.Append($"");
                }
                autoJoinMain.Append($") AS {prefixes[0]}\n");

                for (int i = 1; i < tables.Count; i++) {
                    autoJoinMain.Append($"\t\t{"LEFT"} JOIN {tableNames[i]} AS {prefixes[i]} ON {onclauses[i]}\n");
                }
                AutoJoinCache[inputJoin] = (autoJoinMain);
            }
            Query.Append(AutoJoinCache[inputJoin]);

            if (!isLinedAggregateJoin) {
                if (conditions != null && !conditions.IsEmpty) {
                    Query.Append("\tWHERE");
                    Query.Append(conditions);
                }
                if (orderingMember != null) {
                    Query.Append($"ORDER BY {prefixes[0]}.{orderingMember.Name} {otype.ToString().ToUpper()}");
                }
                if (skip != null || take != null) {
                    Query.Append("LIMIT ");
                    Query.Append(
                        skip != null ? $"{skip},{take ?? Int32.MaxValue}" : $"{take ?? Int32.MaxValue}"
                    );
                }
            }
<commit_msg>Adds parallelism resistance to autocache join query init<commit_after>﻿
/**
 * Figlotech.BDados.Builders.MySqlQueryGenerator
 * MySQL implementation for IQueryGEnerator, used by the MySqlDataAccessor
 * For generating SQL Queries.
 * 
 * @Author: <NAME>
 * August/2014
 * 
**/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Figlotech.BDados.DataAccessAbstractions;
using Figlotech.Core.Interfaces;
using System.Reflection;
using System.Linq.Expressions;
using Figlotech.BDados.Helpers;
using Figlotech.BDados.DataAccessAbstractions.Attributes;
using Figlotech.Core;
using System.Text.RegularExpressions;
using Figlotech.BDados.Builders;
using Figlotech.Core.Helpers;
using System.Diagnostics;

namespace Figlotech.BDados.MySqlDataAccessor {
    public class MySqlQueryGenerator : IQueryGenerator {

        public IQueryBuilder GenerateInsertQuery(IDataObject inputObject) {
            QueryBuilder query = new QbFmt($"INSERT INTO {inputObject.GetType().Name}");
            query.Append("(");
            query.Append(GenerateFieldsString(inputObject.GetType(), true));
            query.Append(")");
            query.Append("VALUES (");
            var members = GetMembers(inputObject.GetType());
            members.RemoveAll(m => m.GetCustomAttribute<PrimaryKeyAttribute>() != null);
            for (int i = 0; i < members.Count; i++) {
                var val = ReflectionTool.GetMemberValue(members[i], inputObject);
                if (val == null) {
                    var pc = members[i].GetCustomAttribute<PreemptiveCounter>();
                    var ic = members[i].GetCustomAttribute<IncrementalCounter>();

                    if (pc != null) {
                        query.Append(pc.OnInsertSubQuery(inputObject.GetType(), members[i]));
                    } else
                    if (ic != null) {
                        query.Append(ic.OnInsertSubQuery(inputObject.GetType(), members[i]));
                    } else {
                        query.Append($"@{members[i].Name}_{i + 1}", val);
                    }
                } else {
                    query.Append($"@{members[i].Name}_{i + 1}", val);
                }

                if (i < members.Count - 1) {
                    query.Append(",");
                }
            }
            query.Append(")");
            //query.Append("ON DUPLICATE KEY UPDATE ");
            //var Fields = GetMembers(inputObject.GetType()).Where(field =>
            //    field.GetCustomAttribute(typeof(PrimaryKeyAttribute)) == null &&
            //    field.GetCustomAttribute(typeof(ReliableIdAttribute)) == null
            //).ToList();
            //for (int i = 0; i < Fields.Count; ++i) {
            //    query.Append(String.Format("{0} = VALUES({0})", Fields[i].Name));
            //    if (i < Fields.Count - 1) {
            //        query.Append(",");
            //    }
            //}
            return query;
        }

        public IQueryBuilder GetCreationCommand(Type t) {
            String objectName = t.Name;

            var members = ReflectionTool.FieldsAndPropertiesOf(t);
            members.RemoveAll(
                (m) => m?.GetCustomAttribute<FieldAttribute>() == null);
            if (objectName == null || objectName.Length == 0)
                return null;
            QueryBuilder CreateTable = new QbFmt($"CREATE TABLE IF NOT EXISTS {objectName} (\n");
            for (int i = 0; i < members.Length; i++) {
                var info = members[i].GetCustomAttribute<FieldAttribute>();
                CreateTable.Append(Fi.Tech.GetColumnDefinition(members[i], info));
                CreateTable.Append(" ");
                CreateTable.Append(info.Options ?? "");
                if (i != members.Length - 1) {
                    CreateTable.Append(", \n");
                }
            }
            CreateTable.Append(" );");
            return CreateTable;
        }

        public IQueryBuilder GenerateCallProcedure(string name, object[] args) {
            QueryBuilder query = new QbFmt($"CALL {name}");
            for (int i = 0; i < args.Length; i++) {
                if (i == 0) {
                    query.Append("(");
                }
                query.Append($"@{i + 1}", args[i]);
                if (i < args.Length - 1)
                    query.Append(",");
                if (i == args.Length - 1) {
                    query.Append(")");
                }
            }
            return query;
        }

        private bool RelatesWithMain(string a) {
            var retv = (a.StartsWith("a.") || a.Contains("=a."));
            return retv;
        }

        static Dictionary<JoinDefinition, QueryBuilder> AutoJoinCache = new Dictionary<JoinDefinition, QueryBuilder>();
        public IQueryBuilder GenerateJoinQuery(JoinDefinition inputJoin, IQueryBuilder conditions, int? skip = null, int? take = null, MemberInfo orderingMember = null, OrderingType otype = OrderingType.Asc, IQueryBuilder rootConditions = null) {
            if (rootConditions == null)
                rootConditions = new QbFmt("true");
            if (inputJoin.Joins.Count < 1)
                throw new BDadosException("This join needs 1 or more tables.");

            List<Type> tables = (from a in inputJoin.Joins select a.ValueObject).ToList();
            List<String> tableNames = (from a in inputJoin.Joins select a.ValueObject.Name).ToList();
            List<String> prefixes = (from a in inputJoin.Joins select a.Prefix).ToList();
            List<String> aliases = (from a in inputJoin.Joins select a.Alias).ToList();
            List<String> onclauses = (from a in inputJoin.Joins select a.Args).ToList();
            List<List<String>> columns = (from a in inputJoin.Joins select a.Columns).ToList();
            List<JoinType> joinTypes = (from a in inputJoin.Joins select a.Type).ToList();

            var isLinedAggregateJoin = false; // && conditions.GetCommandText() == rootConditions.GetCommandText() && conditions.GetParameters().SequenceEqual(rootConditions.GetParameters());

            QueryBuilder Query = new QueryBuilder();

            if (!AutoJoinCache.ContainsKey(inputJoin)) {
                lock (AutoJoinCache) {
                    if (!AutoJoinCache.ContainsKey(inputJoin)) {
                        // By caching this heavy process I might gain loads of performance
                        // When redoing the same queries.
                        QueryBuilder autoJoinMain = new QbFmt("SELECT sub.*\n");
                        autoJoinMain.Append($"\t FROM (SELECT\n");
                        for (int i = 0; i < tables.Count; i++) {
                            autoJoinMain.Append($"\t\t-- Table {tableNames[i]}\n");
                            var ridF = FiTechBDadosExtensions.RidColumnOf[tables[i]];
                            if (!columns[i].Any(c => c.ToUpper() == ridF.ToUpper()))
                                columns[i].Add(ridF);
                            var nonexcl = columns[i];
                            for (int j = 0; j < nonexcl.Count; j++) {
                                autoJoinMain.Append($"\t\t{prefixes[i]}.{nonexcl[j]} AS {prefixes[i]}_{nonexcl[j]},\n");
                            }
                            autoJoinMain.Append("\n");
                        }

                        autoJoinMain.Append($"\t\t1 FROM (SELECT * FROM {tableNames[0]}");

                        if (isLinedAggregateJoin) {
                            if (rootConditions != null) {
                                autoJoinMain.Append("WHERE ");
                                autoJoinMain.Append(rootConditions);
                            }
                            if (orderingMember != null) {
                                autoJoinMain.Append($"ORDER BY {orderingMember.Name} {otype.ToString().ToUpper()}");
                            }
                            if (skip != null || take != null) {
                                autoJoinMain.Append("LIMIT ");
                                autoJoinMain.Append(
                                    skip != null ? $"{skip},{take ?? Int32.MaxValue}" : $"{take ?? Int32.MaxValue}"
                                );
                            }
                            autoJoinMain.Append($"");
                        }
                        autoJoinMain.Append($") AS {prefixes[0]}\n");

                        for (int i = 1; i < tables.Count; i++) {
                            autoJoinMain.Append($"\t\t{"LEFT"} JOIN {tableNames[i]} AS {prefixes[i]} ON {onclauses[i]}\n");
                        }
                        AutoJoinCache[inputJoin] = (autoJoinMain);
                    }
                }
            }
            Query.Append(AutoJoinCache[inputJoin]);

            if (!isLinedAggregateJoin) {
                if (conditions != null && !conditions.IsEmpty) {
                    Query.Append("\tWHERE");
                    Query.Append(conditions);
                }
                if (orderingMember != null) {
                    Query.Append($"ORDER BY {prefixes[0]}.{orderingMember.Name} {otype.ToString().ToUpper()}");
                }
                if (skip != null || take != null) {
                    Query.Append("LIMIT ");
                    Query.Append(
                        skip != null ? $"{skip},{take ?? Int32.MaxValue}" : $"{take ?? Int32.MaxValue}"
                    );
                }
            }

{'fraction_non_alphanumeric': 0.127900154674916, 'fraction_numerical': 0.004053549522641207, 'mean_word_length': 1.601276359600444, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '977430', 'n_tokens_mistral': 5052, 'n_tokens_neox': 4763, 'n_words': 1024}