Esempio n. 1
0
        public static void BuildCommand(OracleCommand cmd, Func<string, OracleParameter> paramUpdater = null, Func<XElement, bool> customTagResolver = null)
        {
            XElement elemSql;
            try
            {
                elemSql = XElement.Parse("<root>" + cmd.CommandText + "</root>", LoadOptions.PreserveWhitespace);
            }
            catch (XmlException ex)
            {
                var tokens = cmd.CommandText.Split(new[] {Environment.NewLine}, StringSplitOptions.None);
                string msg;
                if (ex.LineNumber >= 0 && ex.LineNumber < tokens.Length)
                {
                    msg = tokens[ex.LineNumber - 1];
                }
                else
                {
                    msg = string.Format("Line Number: {0}; LinePosition: {1}", ex.LineNumber, ex.LinePosition);
                }
                throw new ArgumentException(msg, "cmd.CommandText", ex);
            }
            var nav = new XPathEvaluator(p =>
            {
                OracleParameter param;
                if (cmd.Parameters.Contains(p))
                {
                    param = cmd.Parameters[p];
                }
                else
                {
                    param = paramUpdater(p);
                    cmd.Parameters.Add(param);
                }
                return param.Value;
            });
            var toRemove = new HashSet<XElement>();
            foreach (var elem in elemSql.Descendants())
            {
                Debug.Assert(elem != null, "elem != null");
                if (toRemove.Contains(elem.Parent))
                {
                    // Optimization.
                    // Do nothing because the parent has been removed and so this element is irrelevant
                    continue;
                }

                bool bKeep;
                switch (elem.Name.LocalName)
                {
                    case "if":
                        bKeep = EvaluateCondition(nav, elem);
                        break;

                    case "a":
                        //<a pre="(", sep=" OR ", post=")">mri.ia_id = :ia_id</a>
                        var matches = _regexParameters.Matches(elem.Value);
                        // Exception here if multiple parameters are found
                        string varName = matches.Cast<Match>().Select(p => p.Groups["paramName"].Value)
                                .Distinct().Single();
                        string condition = string.Format("${0}", varName);
                        bKeep = nav.Matches(condition);
                        if (bKeep)
                        {
                            bKeep = HandleArrayParamterXml(elem, varName, cmd);
                        }
                        break;

                    case "else":
                        // Keep the else only if all the previous else and if have been removed
                        bKeep = elem.ElementsBeforeSelf().Reverse()
                            .TakeUntil(p => p.Name.LocalName == "if")
                            .All(toRemove.Contains);
                        if (bKeep)
                        {
                            XAttribute attr = elem.Attribute("c");
                            if (attr != null)
                            {
                                bKeep = EvaluateCondition(nav, elem);
                            }
                        }
                        break;

                    default:
                        if (customTagResolver == null)
                        {
                            throw new NotSupportedException(elem.Name.LocalName);
                        }
                        bKeep = customTagResolver(elem);
                        break;
                }
                if (!bKeep)
                {
                    toRemove.Add(elem);
                }
            }

            toRemove.Remove();
            cmd.CommandText = elemSql.Value;
            string[] paramsUsed = _regexParameters.Matches(cmd.CommandText).Cast<Match>()
                .Select(p => p.Groups["paramName"].Value)
                .Distinct(StringComparer.InvariantCultureIgnoreCase)
                .ToArray();

            // Remove excess parameters. Note that we are performing case insensitive comparisons
            string[] paramsUnused = cmd.Parameters.Cast<OracleParameter>()
                .Select(p => p.ParameterName)
                .Except(paramsUsed, StringComparer.InvariantCultureIgnoreCase).ToArray();
            foreach (string name in paramsUnused)
            {
                cmd.Parameters.Remove(cmd.Parameters[name]);
            }

            // Create remaining used parameters
            string[] paramsUncreated = paramsUsed.Except(cmd.Parameters.Cast<OracleParameter>().Select(p => p.ParameterName), StringComparer.InvariantCultureIgnoreCase).ToArray();
            foreach (string name in paramsUncreated)
            {
                cmd.Parameters.Add(paramUpdater(name));
            }
            return;
        }
Esempio n. 2
0
 private static bool EvaluateCondition(XPathEvaluator nav, XElement elem)
 {
     XAttribute attr = elem.Attribute("c");
     string condition;
     if (attr == null)
     {
         // Build the condition. This condition evaluates to true if all parameters found within the clause
         // are not null
         string[] paramsUsed = _regexParameters.Matches(elem.Value).Cast<Match>()
             .Select(p => "$" + p.Groups["paramName"].Value)
             .Distinct(StringComparer.InvariantCultureIgnoreCase)
             .ToArray();
         if (paramsUsed.Length == 0)
         {
             string msg = string.Format("Cannot infer condition. No parameter within {0}", elem.Value);
             throw new Exception(msg);
         }
         condition = string.Join(" and ", paramsUsed);
     }
     else
     {
         condition = attr.Value;
     }
     bool bMatch = nav.Matches(condition);
     return bMatch;
 }