Ejemplo n.º 1
0
        /// <summary>
        /// Determines whether the specified expressions are equal.
        /// </summary>
        /// <param name="x">The first expression to compare.</param>
        /// <param name="y">The second expression to compare.</param>
        /// <returns><see langword="true" /> if the specified expressions are equal; otherwise, <see langword="false" />.</returns>
        /// <exception cref="ArgumentException"><paramref name="x"/> or <paramref name="y"/> are expressions that could not be parsed as a SQL expression.</exception>
        public bool Equals(string x, string y)
        {
            if (ReferenceEquals(x, y))
            {
                return(true);
            }
            if (x is null || y is null)
            {
                return(false);
            }

            var tokenizer = new SqlServerTokenizer();

            var xParseResult = tokenizer.TryTokenize(x);

            if (!xParseResult.HasValue)
            {
                throw new ArgumentException($"Could not parse the '{ nameof(x) }' string as a SQL expression. Given: { x }", nameof(x));
            }

            var yParseResult = tokenizer.TryTokenize(y);

            if (!yParseResult.HasValue)
            {
                throw new ArgumentException($"Could not parse the '{ nameof(y) }' string as a SQL expression. Given: { y }", nameof(y));
            }

            var xTokens = xParseResult.Value.ToList();
            var yTokens = yParseResult.Value.ToList();

            var xCleanedTokens = StripWrappingParens(xTokens);
            var yCleanedTokens = StripWrappingParens(yTokens);

            if (xCleanedTokens.Count != yCleanedTokens.Count)
            {
                return(false);
            }

            for (var i = 0; i < xCleanedTokens.Count; i++)
            {
                var xToken = xCleanedTokens[i];
                var yToken = yCleanedTokens[i];

                if (!TokensEqual(xToken, yToken))
                {
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>
        /// Retrieves all dependencies for an expression.
        /// </summary>
        /// <param name="objectName">The name of an object defined by an expression (e.g. a computed column definition).</param>
        /// <param name="expression">A SQL expression that may contain dependent object names.</param>
        /// <returns>A collection of identifiers found in the expression.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="objectName"/> is <c>null</c>. Alternatively, if <paramref name="expression"/> is <c>null</c>, empty or whitespace.</exception>
        /// <exception cref="ArgumentException">Thrown when <paramref name="expression"/> could not be parsed as a valid SQL expression.</exception>
        /// <remarks>This will also return unqualified identifiers, which may cause ambiguity between object names and column names. Additionally it may return other identifiers, such as aliases or type names.</remarks>
        public IReadOnlyCollection <Identifier> GetDependencies(Identifier objectName, string expression)
        {
            if (objectName == null)
            {
                throw new ArgumentNullException(nameof(objectName));
            }
            if (expression.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(expression));
            }

            var tokenizer = new SqlServerTokenizer();

            var tokenizeResult = tokenizer.TryTokenize(expression);

            if (!tokenizeResult.HasValue)
            {
                throw new ArgumentException($"Could not parse the given expression as a SQL expression. Given: { expression }", nameof(expression));
            }

            var result = new HashSet <Identifier>(Comparer);

            var tokens = tokenizeResult.Value;

            var next = tokens.ConsumeToken();

            while (next.HasValue)
            {
                var sqlIdentifier = SqlServerTokenParsers.QualifiedName(next.Location);
                if (sqlIdentifier.HasValue)
                {
                    var dependentIdentifier = sqlIdentifier.Value;
                    if (!Comparer.Equals(dependentIdentifier.Value, objectName))
                    {
                        result.Add(dependentIdentifier.Value);
                    }

                    next = sqlIdentifier.Remainder.ConsumeToken();
                }
                else
                {
                    next = next.Remainder.ConsumeToken();
                }
            }

            return(result);
        }