private void ResolveIntoClause(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context)
        {
            if (fileIndex < tokens.Length && tokens[fileIndex].Text.ToLower().Equals("into"))
            {
                fileIndex++;
                var target = StatementResolveHelper.ResolveDatabaseObject(tokens, ref fileIndex, context);

                statement.TargetObject = target;
            }
        }
Exemple #2
0
        /// <summary>
        /// ATM this resolver just skips the statement without adding anything to the context
        /// </summary>
        public void Resolve(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context)
        {
            fileIndex += 2; //skip "bulk insert"
            StatementResolveHelper.ResolveDatabaseObject(tokens, ref fileIndex, context);

            if (!tokens[fileIndex].Text.ToLower().Equals("from"))
            {
                throw new InvalidSqlException("Missing 'from'-keyword in bulk insert statement");
            }

            fileIndex++; //skip "from"

            string filePath = tokens[fileIndex].Text;

            fileIndex++; //skip file

            if (tokens[fileIndex].Text.ToLower().Equals("with"))
            {
                fileIndex += 2; //skip "with ("

                int openBracketCounter = 1;

                while (openBracketCounter > 0)
                {
                    if (tokens[fileIndex].Text.Equals(")"))
                    {
                        openBracketCounter--;
                    }
                    if (tokens[fileIndex].Text.Equals("("))
                    {
                        openBracketCounter++;
                    }
                    fileIndex++;
                }
            }
        }
Exemple #3
0
 private DatabaseObject ResolveUsingStatement(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context)
 {
     fileIndex++; //skip 'using'
     return(StatementResolveHelper.ResolveDatabaseObject(tokens, ref fileIndex, context));
 }
Exemple #4
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);
        }
        internal void Resolve(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context)
        {
            fileIndex++; //skip 'with'

            do
            {
                var alias = tokens[fileIndex].Text.ToLower();

                if (string.IsNullOrEmpty(alias))
                {
                    throw new InvalidSqlException("Common table expression must have an alias");
                }

                fileIndex++; //skip alias

                List <Expression> columns = new List <Expression>();

                if (!tokens[fileIndex].Text.Equals("as", StringComparison.InvariantCultureIgnoreCase))
                {
                    if (tokens[fileIndex].Text.Equals("("))
                    {
                        fileIndex++; //skip '('
                    }
                    do
                    {
                        var column = StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context);

                        if (!column.Type.Equals(ExpressionType.COLUMN))
                        {
                            throw new InvalidSqlException("Common Table Expressions only may contain conrete columns");
                        }

                        columns.Add(column);

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

                    if (tokens[fileIndex].Text.Equals(")"))
                    {
                        fileIndex++; //skip ')'
                    }
                }

                fileIndex++; //skip 'as'

                var cte = StatementResolveHelper.ResolveDatabaseObject(tokens, ref fileIndex, context);
                cte.Alias       = alias;
                cte.Type        = DatabaseObjectType.CTE;
                cte.Expressions = columns;

                context.CurrentDatabaseObjectContext.Push(cte);

                if (tokens.Length > fileIndex && tokens[fileIndex].Text.Equals(","))
                {
                    fileIndex++; //skip ','
                    continue;
                }
                else
                {
                    break;
                }
            } while (true);
        }
Exemple #6
0
        /// <summary>
        /// The method of death. Dont change anything. Trust me, just dont.
        /// </summary>
        private static void ResolveConcatenatedConditions(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context, ref bool expectingSecondPart)
        {
            bool expectDatabaseObject            = false;
            bool isSecondPartofBetweenExpression = false;

            do
            {
                if (tokens.Length <= fileIndex)
                {
                    break;
                }

                if (tokens[fileIndex].Text.ToLower().Equals("not") || Operators.IsUnaryOperator(tokens[fileIndex].Text.ToLower()))
                {
                    fileIndex++; //skip operator
                }
                if (IsLogicalExpressionOperator(tokens[fileIndex].Text.ToLower()))
                {
                    fileIndex++;
                }

                if (tokens[fileIndex].Text.Equals("("))
                {
                    fileIndex++; //skip '('
                    ResolveConcatenatedConditions(tokens, ref fileIndex, context, ref expectingSecondPart);
                    fileIndex++; //skip ')'
                }
                else
                {
                    do
                    {
                        if (fileIndex < tokens.Length && tokens[fileIndex].Text.ToLower().Equals("null"))
                        {
                            fileIndex++; //skip null
                        }
                        else if (fileIndex < tokens.Length && (tokens[fileIndex].Text.ToLower().Equals("contains") || tokens[fileIndex].Text.ToLower().Equals("exists")))
                        {
                            var resolver = new TsqlFunctionResolver();
                            resolver.Resolve(tokens, ref fileIndex, context);
                            break;
                        }
                        else if (expectDatabaseObject)
                        {
                            StatementResolveHelper.ResolveDatabaseObject(tokens, ref fileIndex, context);
                        }
                        else
                        {
                            StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context);
                            if (isSecondPartofBetweenExpression)
                            {
                                if (!tokens[fileIndex].Text.ToLower().Equals("and"))
                                {
                                    throw new InvalidSqlException("BETWEEN keyword was not followed by an AND");
                                }

                                fileIndex++; //skip 'AND'
                                StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context);
                                isSecondPartofBetweenExpression = false;
                            }

                            if (fileIndex < tokens.Length && tokens[fileIndex].Text.Equals("escape", StringComparison.InvariantCultureIgnoreCase))
                            {
                                fileIndex += 2; // skip 'escape [pattern]'
                            }
                        }

                        if (expectingSecondPart)
                        {
                            expectingSecondPart = false;
                        }

                        if (fileIndex >= tokens.Length)
                        {
                            break;
                        }

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

                        string possibleLogicalExpressionOperator = tokens[fileIndex].Text.ToLower();

                        if (possibleLogicalExpressionOperator.Equals("is"))
                        {
                            if (expectingSecondPart)
                            {
                                throw new InvalidSqlException("Expression contains multiple logical operators");
                            }

                            expectingSecondPart = true;
                            fileIndex++; // skip 'is'

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

                            continue;
                        }

                        if (possibleLogicalExpressionOperator.Equals("between"))
                        {
                            if (expectingSecondPart)
                            {
                                throw new InvalidSqlException("Expression contains multiple logical operators");
                            }

                            expectingSecondPart = true;
                            fileIndex++; // skip 'between'
                            isSecondPartofBetweenExpression = true;
                            continue;
                        }

                        if (possibleLogicalExpressionOperator.Equals("in"))
                        {
                            if (expectingSecondPart)
                            {
                                throw new InvalidSqlException("Expression contains multiple logical operators");
                            }

                            expectingSecondPart  = true;
                            expectDatabaseObject = true;
                            fileIndex++; // skip 'in'
                            continue;
                        }
                        else
                        {
                            expectDatabaseObject = false;
                        }

                        if (IsLogicalExpressionOperator(tokens[fileIndex].Text))
                        {
                            if (expectingSecondPart)
                            {
                                throw new InvalidSqlException("Expression contains multiple logical operators");
                            }

                            expectingSecondPart = !expectingSecondPart;

                            fileIndex++;
                            continue;
                        }



                        if (tokens[fileIndex].Text.ToLower().Equals("and") && isSecondPartofBetweenExpression)
                        {
                            fileIndex++;
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    } while (true);
                }

                if (tokens.Length > fileIndex && !expectingSecondPart && IsLogicalExpressionOperator(tokens[fileIndex].Text.ToLower()))
                {
                    expectingSecondPart = true;
                    fileIndex++; // skip 'operator'
                    continue;
                }

                if (tokens.Length > fileIndex && (tokens[fileIndex].Text.ToLower().Equals("and") || tokens[fileIndex].Text.ToLower().Equals("or")))
                {
                    fileIndex++;
                    continue;
                }
                else
                {
                    break;
                }
            }while (true);
        }
        public DataManipulation Resolve(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context)
        {
            manipulation = new DataManipulation();

            fileIndex++; //skip 'update'

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

            fileIndex++; //skip 'set'

            do
            {
                //Resolves the target object. Note that this target can be an alias that is resolved later in the FROM statement
                var target = StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context);

                AddTargetObject(target, targetObject);

                fileIndex++;                                                                           //skip '='

                var source = StatementResolveHelper.ResolveExpression(tokens, ref fileIndex, context); //resolve source column
                target.ChildExpressions.Add(source);

                manipulation.Expressions.Add(target);

                if (fileIndex < tokens.Length && tokens[fileIndex].Text.Equals(","))
                {
                    fileIndex++; //skip ','
                    continue;
                }
                else
                {
                    break;
                }
            } while (true);

            var objects = StatementResolveHelper.ResolveFromStatement(tokens, ref fileIndex, context);

            AddObjectsToContext(objects, context);

            if (objects.Count > 1)
            {
                targetObject = AssignRealTarget(objects, targetObject);
                var targetSynonymous = new Expression(ExpressionType.COLUMN)
                {
                    Name = Beautifier.EnhanceNotation(targetObject, InternalConstants.WHOLE_OBJECT_SYNONYMOUS),
                    WholeObjectSynonymous = true
                };

                foreach (var dbo in objects)
                {
                    if (!dbo.Type.Equals(DatabaseObjectType.REAL) || dbo.Equals(targetObject))
                    {
                        continue;
                    }
                    var sourceSynonymous = new Expression(ExpressionType.COLUMN)
                    {
                        Name = Beautifier.EnhanceNotation(dbo, InternalConstants.WHOLE_OBJECT_SYNONYMOUS),
                        WholeObjectSynonymous = true
                    };
                    targetSynonymous.ChildExpressions.Add(sourceSynonymous);
                    manipulation.Expressions.Add(targetSynonymous);
                }
            }

            var beautified = new List <Expression>();

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

            manipulation.Expressions = beautified;

            StatementResolveHelper.ResolveWhereStatement(tokens, ref fileIndex, context);

            PopObjectsFromContextStack(context);

            return(manipulation);
        }
Exemple #8
0
        public DataManipulation Resolve(ReadOnlySpan <TSQLToken> tokens, ref int fileIndex, CompilerContext context)
        {
            manipulation = new DataManipulation();

            fileIndex++; //skip 'insert'

            //TODO Resolve TOP Expression

            if (tokens[fileIndex].Text.ToLower().Equals("into"))
            {
                fileIndex++; //skip 'into'
            }
            targetObject = StatementResolveHelper.ResolveDatabaseObject(tokens, ref fileIndex, context, true);

            DetermineTargetColumns(tokens, ref fileIndex, context);

            //TODO Resolve Table Hint

            if (tokens[fileIndex].Text.Equals("values", StringComparison.InvariantCultureIgnoreCase))
            {
                fileIndex += 2; //skip 'values ('
                DetermineSourceObjects(tokens, ref fileIndex, context);
            }
            else if (tokens[fileIndex].Text.Equals("select", StringComparison.InvariantCultureIgnoreCase))
            {
                var selectStatement = new SelectStatementResolver().Resolve(tokens, ref fileIndex, context);
                sources = selectStatement.ChildExpressions;
            }

            if (targets.Count == 0)
            {
                for (int index = 0; index < sources.Count; index++)
                {
                    Expression resolvedSource;

                    if (sources[index].Type.Equals(ExpressionType.COMPLEX) || sources[index].Type.Equals(ExpressionType.CONSTANT))
                    {
                        continue;
                    }
                    else if (sources[index].Type.Equals(ExpressionType.ALIAS))
                    {
                        resolvedSource = sources[index].ChildExpressions[0];
                    }
                    else
                    {
                        resolvedSource = sources[index];
                    }

                    var singleManipulation = new Expression(ExpressionType.COLUMN)
                    {
                        Name = Beautifier.EnhanceNotation(targetObject, InternalConstants.UNRELATED_COLUMN_NAME)
                    };

                    singleManipulation.ChildExpressions.Add(resolvedSource);
                    manipulation.Expressions.Add(singleManipulation);
                }
            }
            else if (StatementResolveHelper.HaveEqualAmountOfRealExpression(sources, targets))
            {
                for (int index = 0; index < targets.Count; index++)
                {
                    if (!sources[index].Type.Equals(ExpressionType.COLUMN) && !sources[index].Type.Equals(ExpressionType.SCALAR_FUNCTION))
                    {
                        continue;
                    }

                    var singleManipulation = new Expression(ExpressionType.COLUMN)
                    {
                        Name = targets[index].Name
                    };

                    singleManipulation.ChildExpressions.Add(sources[index]);
                    manipulation.Expressions.Add(singleManipulation);
                }
            }
            else
            {
                throw new InvalidSqlException("Amount of targets does not match the number of sources");
            }

            if (fileIndex < tokens.Length && tokens[fileIndex].Text.Equals(";"))
            {
                fileIndex++;
            }

            var beautified = new List <Expression>();

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

            manipulation.Expressions = beautified;

            return(manipulation);
        }