Beispiel #1
0
        /// <summary>
        /// Creates a shallow copy of the <see cref="ParameterManager"/> in which <see cref="ParametersFoundSoFarInQueryGeneration"/> is a new
        /// instance but the parameters referenced are shared (with the original).
        /// </summary>
        /// <returns></returns>
        public ParameterManager Clone()
        {
            var clone = new ParameterManager(this.ParametersFoundSoFarInQueryGeneration[ParameterLevel.Global].ToArray());

            clone.State = State;

            foreach (var kvp in ParametersFoundSoFarInQueryGeneration)
            {
                clone.ParametersFoundSoFarInQueryGeneration[kvp.Key].AddRange(kvp.Value);
            }

            return(clone);
        }
Beispiel #2
0
        /// <summary>
        /// Returns all <see cref="ISqlParameter"/> that collide with <paramref name="other"/> (same name different value)
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public string[] GetCollisions(ParameterManager other)
        {
            var pm = new ParameterManager();

            pm.ImportAndElevateResolvedParametersFromSubquery(this, out Dictionary <string, string> subs);

            //not sure how there could be collisions given we went into a fresh one but I guess it would count
            if (subs.Keys.Any())
            {
                return(subs.Keys.ToArray());
            }

            pm.ImportAndElevateResolvedParametersFromSubquery(other, out subs);

            return(subs.Keys.ToArray());
        }
Beispiel #3
0
        /// <summary>
        /// Imports novel <see cref="ISqlParameter"/> from <paramref name="other"/> without renaming.
        /// </summary>
        /// <param name="other"></param>
        /// <exception cref="QueryBuildingException">Thrown if there are non identical parameter name collisions (same name different value)</exception>
        public void MergeWithoutRename(ParameterManager other)
        {
            var collisions = GetCollisions(other);

            if (collisions.Any())
            {
                throw new QueryBuildingException("PatientIndexTables cannot have parameters with the same name as their users.  Offending parameter(s) were " + string.Join(",", collisions));
            }

            foreach (ParameterLevel l in Enum.GetValues(typeof(ParameterLevel)))
            {
                var to   = ParametersFoundSoFarInQueryGeneration[l];
                var from = other.ParametersFoundSoFarInQueryGeneration[l];

                //add all paramters which are not already represented with an identical parameter
                to.AddRange(from.Where(f => !to.Any(t => AreIdentical(f, t))));
            }
        }
Beispiel #4
0
        /// <summary>
        /// Imports all TableInfo level paramaters into a super set (with all TableInfo level paramaters from every manager you have imported).  Also imports all
        /// QueryLevel parameters but for these it will do renames where there are conflicting named parameters, you must
        ///
        /// </summary>
        /// <param name="toImport"></param>
        /// <param name="parameterNameSubstitutions"></param>
        public void ImportAndElevateResolvedParametersFromSubquery(ParameterManager toImport, out Dictionary <string, string> parameterNameSubstitutions)
        {
            if (toImport == this)
            {
                throw new InvalidOperationException("Cannot import parameters into yourself!");
            }

            if (State == ParameterManagerLifecycleState.Finalized)
            {
                throw new InvalidOperationException("Cannot import parameters because state of ParameterManager is already " + ParameterManagerLifecycleState.Finalized);
            }

            if (toImport.ParametersFoundSoFarInQueryGeneration[ParameterLevel.CompositeQueryLevel].Any())
            {
                throw new ArgumentException("Cannot import from ParameterManager because it has 1+ " + ParameterLevel.CompositeQueryLevel + " parameters in it too!");
            }

            parameterNameSubstitutions = new Dictionary <string, string>();

            ////////////////////////////////////////////////////////////Handle TableInfo level parameters//////////////////////////////////////
            //for each table valued parameter (TableInfo level)
            foreach (ISqlParameter parameterToImport in toImport.ParametersFoundSoFarInQueryGeneration[ParameterLevel.TableInfo])
            {
                //it does not already exist
                if (!ParametersFoundSoFarInQueryGeneration[ParameterLevel.CompositeQueryLevel].Any(p => p.ParameterName.Equals(parameterToImport.ParameterName, StringComparison.CurrentCultureIgnoreCase)))
                {
                    ParametersFoundSoFarInQueryGeneration[ParameterLevel.TableInfo].Add(parameterToImport); //import it
                }
                //Do not handle renaming here because it is likely the user doesn't even know this parameter exists as it is a tableinfo level one i.e. a default they declared when they first imported their table valued fuction (or there is a QueryLevel override anyway)
            }
            toImport.ParametersFoundSoFarInQueryGeneration[ParameterLevel.TableInfo].Clear();
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


            //////////////////////////////////////////////////////Handle all the other parameters//////////////////////////////////////////////
            //for each Query Level parameter
            foreach (ISqlParameter parameterToImport in toImport.GetFinalResolvedParametersList())
            {
                string toImportParameterName = parameterToImport.ParameterName;
                var    existing = ParametersFoundSoFarInQueryGeneration[ParameterLevel.CompositeQueryLevel].SingleOrDefault(p => p.ParameterName.Equals(toImportParameterName, StringComparison.CurrentCultureIgnoreCase));

                if (existing == null)
                {
                    ParametersFoundSoFarInQueryGeneration[ParameterLevel.CompositeQueryLevel].Add(parameterToImport);        //import it to the composite level
                }
                else
                {
                    //we are importing SqlParameters from a subquery and we have found a parameter with the same name as one that is already contained at this composite level

                    //if the one we are importing is 100% identical (same declaration and value) then we don't need to import it
                    if (AreIdentical(existing, parameterToImport))
                    {
                        continue;//skip it
                    }
                    //it is different so we have to handle the conflict.  This could be because user has a filter @icdCode in 2 datasets with 2 different meanings and 2 different values

                    //however! if we have a global override configured for this parameter
                    var overridingGlobal = GetOverrideIfAnyFor(existing);

                    //with the same declaration SQL then we can discard the parameter because all values are going to be replaced by the global anyway!
                    if (overridingGlobal != null)
                    {
                        if (AreDeclaredTheSame(overridingGlobal, parameterToImport))
                        {
                            continue;//override will replace both so don't bother importing it
                        }
                        else
                        {
                            //Theres an override with the same name but different datatypes (that's a problem)
                            throw new QueryBuildingException("Parameter " + parameterToImport + " has the same name as an existing parameter with a global override but differing declarations (normally we would handle with a rename but we can't because of the overriding global)", new object[] { existing, parameterToImport, overridingGlobal });
                        }
                    }

                    //one already exists so we will have to do a parameter rename

                    //get the next number going e.g. _2 or _3 etc
                    int newSuffix = GetSuffixForRenaming(toImportParameterName);

                    //Add the rename operation to the audit
                    parameterNameSubstitutions.Add(toImportParameterName, parameterToImport + "_" + newSuffix);

                    //do the rename operation into a spontaneous object because modifying the ISqlParameter directly could corrupt it for other users (especially if SuperCaching is on! See RDMPDEV-668)
                    var spont = new SpontaneouslyInventedSqlParameter(
                        _memoryRepository,
                        parameterToImport.ParameterSQL.Replace(toImportParameterName, parameterToImport + "_" + newSuffix),
                        parameterToImport.Value,
                        parameterToImport.Comment,
                        parameterToImport.GetQuerySyntaxHelper()
                        );

                    //now make it a composite query level parameter used by us
                    ParametersFoundSoFarInQueryGeneration[ParameterLevel.CompositeQueryLevel].Add(spont);
                }
            }
        }