Пример #1
0
        /// <summary>
        /// Checks if a when expression is set within the MERGE-statement and resolves it if so
        /// </summary>
        private void ResolveWhenExpression(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context)
        {
            if (!tokens[fileIndex].Text.Equals("when", StringComparison.InvariantCultureIgnoreCase))
            {
                return;
            }
            else
            {
                fileIndex++; //skip 'when'
            }
            if (tokens[fileIndex].Text.Equals("matched", StringComparison.InvariantCultureIgnoreCase))
            {
                fileIndex++; //skip 'matched'
                if (tokens[fileIndex].Text.Equals("and", StringComparison.InvariantCultureIgnoreCase))
                {
                    fileIndex++; //skip 'and'
                    SearchConditionResolver.Resolve(tokens, ref fileIndex, context);
                }

                if (!tokens[fileIndex].Text.Equals("then", StringComparison.InvariantCultureIgnoreCase))
                {
                    throw new InvalidSqlException("WHEN-expression does not contain the THEN-Keyword");
                }
                else
                {
                    fileIndex++; //skip 'then'
                    ResolveMergeMatched(tokens, ref fileIndex, context);
                }
            }
            else if (tokens[fileIndex].Text.Equals("not", StringComparison.InvariantCultureIgnoreCase))
            {
                fileIndex += 2; //skip 'not matched'

                if (tokens[fileIndex].Text.Equals("by", StringComparison.InvariantCultureIgnoreCase))
                {
                    fileIndex++; //skip 'by'
                    if (tokens[fileIndex].Text.Equals("source", StringComparison.InvariantCultureIgnoreCase))
                    {
                        fileIndex++; //skip source

                        if (tokens[fileIndex].Text.Equals("and", StringComparison.InvariantCultureIgnoreCase))
                        {
                            fileIndex++; //skip 'and'
                            SearchConditionResolver.Resolve(tokens, ref fileIndex, context);
                        }

                        if (!tokens[fileIndex].Text.Equals("then", StringComparison.InvariantCultureIgnoreCase))
                        {
                            throw new InvalidSqlException("WHEN-expression does not contain the THEN-Keyword");
                        }
                        else
                        {
                            fileIndex++; //skip 'then'
                            ResolveMergeMatched(tokens, ref fileIndex, context);
                        }

                        return;
                    }
                    if (tokens[fileIndex].Text.Equals("target", StringComparison.InvariantCultureIgnoreCase))
                    {
                        fileIndex++;
                    }
                }

                if (tokens[fileIndex].Text.Equals("and", StringComparison.InvariantCultureIgnoreCase))
                {
                    fileIndex++; //skip 'and'
                    SearchConditionResolver.Resolve(tokens, ref fileIndex, context);
                }

                if (!tokens[fileIndex].Text.Equals("then", StringComparison.InvariantCultureIgnoreCase))
                {
                    throw new InvalidSqlException("WHEN-expression does not contain the THEN-Keyword");
                }
                else
                {
                    fileIndex++; //skip 'then'
                    ResolveMergeNotMatched(tokens, ref fileIndex, context);
                }
            }
            else
            {
                throw new InvalidSqlException("Invalid WHEN-expression within MERGE-statement");
            }
        }
Пример #2
0
        public DataManipulation Resolve(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context)
        {
            manipulation = new DataManipulation();

            fileIndex++; //skip "merge"

            //skip top expression
            SkipTopExpression(tokens, ref fileIndex, context);

            if (tokens[fileIndex].Text.ToLower().Equals("into"))
            {
                fileIndex++;
            }

            targetObject = StatementResolveHelper.ResolveDatabaseObject(tokens, ref fileIndex, context);

            context.AddDatabaseObjectToCurrentContext(targetObject);

            if (!tokens[fileIndex].Text.ToLower().Equals("using"))
            {
                throw new InvalidSqlException("Trying to resolve a merge-statement without using keyword");
            }

            var source = ResolveUsingStatement(tokens, ref fileIndex, context);

            context.AddDatabaseObjectToCurrentContext(source);

            if (!tokens[fileIndex].Text.Equals("on", StringComparison.InvariantCultureIgnoreCase))
            {
                throw new InvalidSqlException("Expected 'ON' keyword when resolving a 'MERGE'-statement");
            }

            fileIndex++; //skip 'on'

            SearchConditionResolver.Resolve(tokens, ref fileIndex, context);

            while (tokens[fileIndex].Text.Equals("when", StringComparison.InvariantCultureIgnoreCase))
            {
                ResolveWhenExpression(tokens, ref fileIndex, context);
            }

            var beautified = new List <Expression>();

            foreach (var exp in manipulation.Expressions)
            {
                beautified.Add(Beautifier.BeautifyColumns(exp, context));
            }

            manipulation.Expressions = beautified;

            while (!tokens[fileIndex].Text.ToLower().Equals(";"))
            {
                fileIndex++;
                if (fileIndex == tokens.Length)
                {
                    throw new InvalidSqlException("Trying to resolve a merge-statement without proper ';' determination");
                }
            }

            fileIndex++; //skip ';'

            context.CurrentDatabaseObjectContext.Pop();

            return(manipulation);
        }
        public Expression Resolve(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context)
        {
            List <Expression> expressions = new List <Expression>();

            // The CASE expression has two formats: 'simple' and 'searched'. For more information visit:
            // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql?view=sql-server-2017
            bool isSimpleFormat = false;

            fileIndex++; //skip "case"

            if (!tokens[fileIndex].Text.ToLower().Equals("when"))
            {
                isSimpleFormat = true;
                StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context);
            }

            do
            {
                fileIndex++; //skip 'when'

                if (isSimpleFormat)
                {
                    StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context);
                }
                else
                {
                    SearchConditionResolver.Resolve(tokens, ref fileIndex, context);
                }

                fileIndex++; //skip 'then'

                Expression thenExpression = StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context);
                if (thenExpression.Type.Equals(ExpressionType.COLUMN))
                {
                    expressions.Add(thenExpression);
                }
                else if (thenExpression.Type.Equals(ExpressionType.COMPLEX) || thenExpression.Type.Equals(ExpressionType.SCALAR_FUNCTION))
                {
                    expressions.AddRange(thenExpression.ChildExpressions);
                }

                if (tokens.Length <= fileIndex)
                {
                    throw new InvalidSqlException("Trying to resolve case-statement without 'end'-keyword");
                }

                if (tokens[fileIndex].Text.ToLower().Equals("when"))
                {
                    continue;
                }

                if (tokens[fileIndex].Text.ToLower().Equals("else"))
                {
                    fileIndex++; //skip 'else'
                    Expression elseExpression = StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context);
                    if (elseExpression.Type.Equals(ExpressionType.COLUMN))
                    {
                        expressions.Add(elseExpression);
                    }
                    else if (elseExpression.Type.Equals(ExpressionType.COMPLEX) || elseExpression.Type.Equals(ExpressionType.SCALAR_FUNCTION))
                    {
                        expressions.AddRange(elseExpression.ChildExpressions);
                    }
                }

                if (tokens[fileIndex].Text.ToLower().Equals("end"))
                {
                    fileIndex++; //skip 'end'
                    break;
                }
            } while (true);

            if (expressions.Count == 1)
            {
                return(expressions[0]);
            }
            else
            {
                return(new Expression(ExpressionType.SCALAR_FUNCTION)
                {
                    Name = "CASE",
                    ChildExpressions = expressions
                });
            }
        }