/// <summary>
 /// конструктор с параметрами
 /// </summary>
 /// <param name="Name"></param>
 /// <param name="pars"></param>
 /// <param name="Func"></param>
 /// <param name="custString"></param>
 /// <param name="pV"></param>
 /// <param name="LookUps"></param>
 public AdvansedLimit(string Name, ParameterDef[] pars, FunctionalLanguage.Function Func, string custString, SortedList pV, Hashtable LookUps)
 {
     this.Name           = Name;
     Parameters          = pars;
     Function            = Func;
     FormCustomizeString = custString;
     paramValues         = pV;
     this.LookUps        = LookUps;
 }
        /// <summary>
        /// Возвращает индексы и ключи объектов, встретившихся в массиве,
        /// при загрузке по указанному lcs. Объекты задаются через lf.
        /// </summary>
        /// <param name="lcs">Массив, в котором ищем.</param>
        /// <param name="limitFunction">Функция ограничения, определяющая искомые объекты.</param>
        /// <param name="maxResults">
        /// Максимальное число возвращаемых результатов.
        /// Этот параметр не соответствует <code>lcs.ReturnTop</code>, а устанавливает максимальное число
        /// искомых объектов, тогда как <code>lcs.ReturnTop</code> ограничивает число объектов, в которых
        /// проводится поиск.
        /// Если значение не определено (<c>null</c>), то возвращаются все найденные результаты.
        /// </param>
        /// <returns>
        /// Массив индексов найденных объектов начиная с 1. Не возвращает null.
        /// </returns>
        public override IDictionary <int, string> GetObjectIndexesWithPks(
            LoadingCustomizationStruct lcs,
            FunctionalLanguage.Function limitFunction,
            int?maxResults = null)
        {
            if (countGenerateSqlSelect == 0)
            {
                isGenerateSqlSelect = true;
            }

            countGenerateSqlSelect++;
            IDictionary <int, string> ret = GetObjectIndexesWithPksImplementation(lcs, limitFunction, maxResults);

            countGenerateSqlSelect--;
            if (countGenerateSqlSelect == 0)
            {
                isGenerateSqlSelect = false;
            }

            return(ret);
        }
 /// <summary>
 /// Синхронизация параметров функции с параметрами текущего объекта (параметрам функции присвоятся параметры текущего объекта при совпадении имён)
 /// </summary>
 /// <param name="func"></param>
 private void SyncParams(FunctionalLanguage.Function func)
 {
     for (int i = 0; i < func.Parameters.Count; i++)
     {
         object o = func.Parameters[i];
         if (o is FunctionalLanguage.Function)
         {
             SyncParams(o as FunctionalLanguage.Function);
         }
         else if (o is ParameterDef)
         {
             ParameterDef op = o as ParameterDef;
             foreach (ParameterDef pd in Parameters)
             {
                 if (pd.ParamName == op.ParamName)
                 {
                     func.Parameters[i] = pd;
                     break;
                 }
             }
         }
     }
 }
        /// <summary>
        /// !!! Сделано public для обратной совместимости, использовать аккуратно.
        /// Берутся значения из глобальной переменной edobj и впариваются в функцию вместо параметров
        /// TODO: переписать эту функцию так, чтобы глобальная переменная не применялась и сделать её публичной
        /// </summary>
        /// <param name="func"></param>
        /// <returns></returns>
        public Function ConvertFunction(Function func)
        {
            if (func == null)
            {
                return(null);
            }

            FunctionalLanguage.Function res = new ICSSoft.STORMNET.FunctionalLanguage.Function(func.FunctionDef);
            ArrayList pars = new ArrayList();

            pars.AddRange(func.Parameters);
            for (int i = 0; i < pars.Count; i++)
            {
                if (pars[i] is FunctionalLanguage.Function)
                {
                    FunctionalLanguage.Function cur_func = pars[i] as FunctionalLanguage.Function;
                    pars[i] = ConvertFunction(cur_func);
                }
                else if (pars[i] is ParameterDef)
                {
                    object val = ICSSoft.STORMNET.Information.GetPropValueByName(edobj, (pars[i] as ParameterDef).ParamName);
                    if (val is DetailArray)
                    {
                        DetailArray  dar  = val as DetailArray;
                        DataObject[] objs = dar.GetAllObjects();
                        foreach (DataObject obj in objs)
                        {
                            if (obj.GetStatus(false) == ObjectStatus.Deleted)
                            {
                                dar.Remove(obj);
                            }
                            else
                            {
                                object ops = ICSSoft.STORMNET.Information.GetPropValueByName(obj, (pars[i] as ParameterDef).ParamName);
                                if (ops == null)
                                {
                                    dar.Remove(obj);
                                }
                            }
                        }

                        object[] pp = new object[dar.Count];
                        for (int j = 0; j < pp.Length; j++)
                        {
                            pp[j] = ICSSoft.STORMNET.Information.GetPropValueByName(dar.ItemByIndex(j), (pars[i] as ParameterDef).ParamName);
                        }

                        if (func.FunctionDef.Parameters[func.FunctionDef.Parameters.Count - 1].MultiValueSupport)
                        {
                            pars.RemoveAt(i);
                            pars.InsertRange(i, pp);
                        }
                        else
                        if (pp.Length > 0)
                        {
                            pars[i] = pp[0];
                        }
                        else
                        {
                            pars[i] = null;
                        }

                        i--;
                    }
                    else
                    {
                        pars[i] = ICSSoft.STORMNET.Information.GetPropValueByName(edobj, (pars[i] as ParameterDef).ParamName);
                    }
                }
                else if (func.FunctionDef.StringedView == "SQL" && ICSSoft.STORMNET.Business.DataServiceProvider.DataService is ICSSoft.STORMNET.Business.SQLDataService)
                {
                    ICSSoft.STORMNET.Business.SQLDataService ds = (ICSSoft.STORMNET.Business.SQLDataService)ICSSoft.STORMNET.Business.DataServiceProvider.DataService;

                    string sSQl = pars[i].ToString();

                    int j;

                    while ((j = sSQl.IndexOf("@")) != -1)
                    {
                        int k = j + 1;
                        while (k < sSQl.Length && (char.IsLetterOrDigit(sSQl[k]) || sSQl[k] == '_'))
                        {
                            k++;
                        }

                        string sParamName = sSQl.Substring(j, k - j);
                        sSQl = sSQl.Remove(j, k - j);

                        string sParamValue = string.Empty;

                        foreach (ParameterDef p in Parameters)
                        {
                            if ("@" + p.ParamName == sParamName)
                            {
                                sParamValue = ds.ConvertSimpleValueToQueryValueString(ICSSoft.STORMNET.Information.GetPropValueByName(edobj, p.ParamName));
                                break;
                            }
                        }

                        sSQl = sSQl.Insert(j, sParamValue);
                    }

                    pars[i] = sSQl;
                }
            }

            res.Parameters.AddRange(pars);
            return(res);
        }
        private IDictionary <int, string> GetObjectIndexesWithPksImplementation(
            LoadingCustomizationStruct lcs,
            FunctionalLanguage.Function limitFunction,
            int?maxResults = null)
        {
            string nl  = Environment.NewLine;
            var    ret = new Dictionary <int, string>();

            if (lcs == null || limitFunction == null)
            {
                return(ret);
            }

            if (maxResults.HasValue && maxResults < 0)
            {
                throw new ArgumentOutOfRangeException("maxResults", "Максимальное число возвращаемых результатов не может быть отрицательным.");
            }

            if (!DoNotChangeCustomizationString && ChangeCustomizationString != null)
            {
                string cs = ChangeCustomizationString(lcs.LoadingTypes);
                CustomizationString = string.IsNullOrEmpty(cs) ? CustomizationString : cs;
            }

            bool usedSorting = false;

            if (lcs.ColumnsSort == null || lcs.ColumnsSort.Length == 0)
            {
                lcs.ColumnsSort = new[] { new ColumnsSortDef("__PrimaryKey", SortOrder.Asc) };
            }
            else
            {
                usedSorting = true;
            }

            string innerQuery = GenerateSQLSelect(lcs, false);
            string offset     = null;

            if (lcs.RowNumber != null)
            {
                int posOffset = innerQuery.LastIndexOf("OFFSET ");
                offset     = innerQuery.Substring(posOffset);
                innerQuery = innerQuery.Substring(0, posOffset);

                // + nl + "where \"RowNumber\" between " + lcs.RowNumber.StartRow.ToString() + " and " + lcs.RowNumber.EndRow.ToString() + nl;
            }

            // надо добавить RowNumber
            // top int.MaxValue
            int    orderByIndex = usedSorting ? innerQuery.ToLower().LastIndexOf("order by ") : -1;
            string orderByExpr  = string.Empty; // , nl = Environment.NewLine;

            if (orderByIndex > -1)
            {
                orderByExpr = innerQuery.Substring(orderByIndex);
            }

            int fromInd = innerQuery.ToLower().IndexOf("from");

            if (!string.IsNullOrEmpty(orderByExpr))
            {
                innerQuery = innerQuery.Substring(0, innerQuery.Length - orderByExpr.Length);
                innerQuery = innerQuery.Insert(fromInd, "," + nl + "row_number() over (" + orderByExpr + ") as \"RowNumber\"" + nl);
            }
            else
            {
                innerQuery = innerQuery.Insert(fromInd, "," + nl + "row_number() over (ORDER BY " + PutIdentifierIntoBrackets("STORMMainObjectKey") + " ) as \"RowNumber\"" + nl);
            }

            if (lcs.RowNumber != null)
            {
                innerQuery += nl + "where \"RowNumber\" between " + lcs.RowNumber.StartRow.ToString() + " and " + lcs.RowNumber.EndRow.ToString() + nl;
            }

            string query = string.Format(
                "SELECT{3} \"RowNumber\", {5} FROM {1}({0}) QueryForGettingIndex {1} WHERE ({2}) {4}",
                innerQuery,
                nl,
                LimitFunction2SQLWhere(limitFunction),
                maxResults.HasValue ? (" TOP " + maxResults) : string.Empty,
                orderByExpr,
                PutIdentifierIntoBrackets("STORMMainObjectKey"));

            // if (offset != null)
            //    query += nl + offset;
            object state = null;

            object[][] res = ReadFirst(query, ref state, lcs.LoadingBufferSize);
            if (res != null)
            {
                for (int i = 0; i < res.Length; i++)
                {
                    object pk = res[i][1];

                    pk = Information.TranslateValueToPrimaryKeyType(lcs.LoadingTypes[0], pk);

                    ret[(int)Convert.ChangeType(res[i][0], typeof(int))] = pk.ToString();
                }

                return(ret);
            }

            return(ret);
        }