public TokenParserResults Parse(ParseArgs <SelectStatement> parseArgs)
        {
            var selectStatement = parseArgs.Statement;
            var args            = parseArgs.StatementArgs;

            var results = new TokenParserResults();

            var words = ParserUtils.GetWords(args).ToList();

            if (words.Any())
            {
                var columns = ParserUtils.SplitTokens(words);

                foreach (var wordList in columns)
                {
                    SelectFromBase selectFrom = null;

                    var startWord = wordList[0];

                    if (wordList.Count > 3)
                    {
                        results.Errors.Add(new SqlStatementError("Unknown tokens", 0));

                        return(results);
                    }
                    else if (wordList.Count == 3)
                    {
                        if (wordList[1] != "as")
                        {
                            results.Errors.Add(new SqlStatementError("Expecting 'As' keyword", 0));

                            return(results);
                        }

                        selectFrom = new SelectFrom(startWord, wordList[2]);
                    }
                    else if (wordList.Count == 2)
                    {
                        selectFrom = new SelectFrom(startWord, wordList[1]);
                    }
                    else
                    {
                        selectFrom = new SelectFrom(startWord);
                    }

                    if (selectFrom != null)
                    {
                        selectStatement.From.Add(selectFrom);
                    }
                }
            }

            return(results);
        }
Beispiel #2
0
        public Result <SelectStatement, SqlStatementError> ParseSelect(SqlStatement statement)
        {
            var selectStatement = new SelectStatement();

            var errors = new List <SqlStatementError>();

            var rules = Configuration.SelectStatementConfiguration.Rules();

            var args  = new Dictionary <string, string>();
            var words = ParserUtils.GetWords(statement.Sql).ToList();

            if (words.First() != "select")
            {
                errors.Add(new SqlStatementError("No 'Select' statement found.", 0));
            }
            else
            {
                var currentIndex = 0;

                while (true)
                {
                    var word = words[currentIndex];

                    var rule = rules.SingleOrDefault(x => x.Name == word);

                    if (rule == null)
                    {
                        break;
                    }

                    if (rule.NextTokens.Any())
                    {
                        int?nextTokenIndex = null;

                        foreach (var nextToken in rule.NextTokens)
                        {
                            nextTokenIndex = FindInArray(words, currentIndex, nextToken);

                            if (nextTokenIndex.HasValue)
                            {
                                break;
                            }
                        }

                        if (rule.RequiresNextToken && nextTokenIndex.HasValue == false)
                        {
                            errors.Add(new SqlStatementError($"Incomplete statement after {word}", 0));
                            break;
                        }

                        if (rule.Args)
                        {
                            var count = nextTokenIndex.HasValue
                                ? nextTokenIndex.Value - currentIndex - 1
                                : words.Count - currentIndex - 1;

                            var tokenArgs = string.Join(" ", words.GetRange(currentIndex + 1, count));

                            if (string.IsNullOrWhiteSpace(tokenArgs))
                            {
                                errors.Add(new SqlStatementError($"Expected arguments after {word}", 0));
                                break;
                            }

                            args.Add(word, tokenArgs);
                        }

                        currentIndex = nextTokenIndex ?? words.Count - 1;
                    }
                    else
                    {
                        if (rule.Args)
                        {
                            var tokenArgs = string.Join(" ", words.GetRange(currentIndex + 1, words.Count - currentIndex - 1));

                            if (string.IsNullOrWhiteSpace(tokenArgs))
                            {
                                errors.Add(new SqlStatementError($"Expected arguments after {word}", 0));
                                break;
                            }

                            args.Add(word, tokenArgs);

                            break;
                        }
                    }
                }
            }

            foreach (var token in args.Keys)
            {
                var tokenPath = "select." + token;

                var parsers = Configuration.SelectStatementConfiguration.Parsers().Where(x => string.Equals(x.TokenPath, tokenPath));

                foreach (var parser in parsers)
                {
                    var parseArgs = new ParseArgs <SelectStatement>()
                    {
                        Statement        = selectStatement,
                        StatementArgs    = args[token],
                        StatementsParser = this
                    };

                    var parseResults = tokenPath == "select.select"
                        ? new SelectStatementTokenSelectParser().Parse(parseArgs)
                        : parser.Parse(parseArgs);

                    if (parseResults.Errors.Any())
                    {
                        errors.AddRange(parseResults.Errors);
                    }
                }
            }

            var result = new Result <SelectStatement, SqlStatementError>(selectStatement)
            {
                Errors = errors
            };

            return(result);
        }
Beispiel #3
0
        public TokenParserResults Parse(ParseArgs <SelectStatement> parseArgs)
        {
            var selectStatement = parseArgs.Statement;
            var args            = parseArgs.StatementArgs;

            var results = new TokenParserResults();

            var words = ParserUtils.GetWords(args).ToList();

            var segments = ParserUtils.SplitTokens(words);

            foreach (var wordList in segments)
            {
                if (wordList.Any() == false)
                {
                    results.Errors.Add(new SqlStatementError("No order clause specified", 0));

                    return(results);
                }

                SelectOrderBase orderColumn = null;

                var startWord = wordList[0];

                var number = 0;

                if (int.TryParse(startWord, out number))
                {
                    if (wordList.Count > 2)
                    {
                        results.Errors.Add(new SqlStatementError("Unknown tokens", 0));

                        return(results);
                    }
                    else if (wordList.Count == 2)
                    {
                        if (wordList[1] != "asc" && wordList[1] != "desc")
                        {
                            results.Errors.Add(new SqlStatementError("Expecting 'Asc' or 'Desc' keyword", 0));

                            return(results);
                        }

                        var sortDirection = wordList[1] == "asc" ? OrderDirection.Asc : OrderDirection.Desc;

                        orderColumn = new SelectOrderPosition(number, sortDirection);
                    }
                    else if (wordList.Count == 1)
                    {
                        orderColumn = new SelectOrderPosition(number);
                    }
                }
                else if (startWord.StartsWith("'") && startWord.EndsWith("'"))
                {
                    results.Errors.Add(new SqlStatementError("A constant expression was encountered in the ORDER BY list", 0));

                    return(results);
                }
                else if (char.IsLetter(startWord[0]))
                {
                    if (wordList.Count > 2)
                    {
                        results.Errors.Add(new SqlStatementError("Unknown tokens", 0));

                        return(results);
                    }
                    else if (wordList.Count == 2)
                    {
                        if (wordList[1] != "asc" && wordList[1] != "desc")
                        {
                            results.Errors.Add(new SqlStatementError("Expecting 'Asc' or 'Desc' keyword", 0));

                            return(results);
                        }

                        var sortDirection = wordList[1] == "asc" ? OrderDirection.Asc : OrderDirection.Desc;

                        orderColumn = new SelectOrderColumn(startWord, sortDirection);
                    }
                    else if (wordList.Count == 1)
                    {
                        orderColumn = new SelectOrderColumn(startWord);
                    }
                }

                if (orderColumn == null)
                {
                    throw new NotSupportedException();
                }

                selectStatement.Order.Add(orderColumn);
            }

            return(results);
        }
Beispiel #4
0
        public TokenParserResults Parse(ParseArgs <SelectStatement> parseArgs)
        {
            var selectStatement = parseArgs.Statement;
            var args            = parseArgs.StatementArgs;

            var results = new TokenParserResults();

            var words = GetWords != null
                ? GetWords(args).ToList()
                : ParserUtils.GetWords(args).ToList();

            if (words.Any())
            {
                var currentGroup = new SelectWhereGroup();
                var groupStack   = new Stack <SelectWhereGroup>();
                var clauseWords  = new List <string>();

                for (int i = 0; i < words.Count; i++)
                {
                    var word = words[i];

                    if (word.In("(", ")", "and", "or"))
                    {
                        ParseClauseWords(clauseWords, currentGroup);
                    }

                    if (word == "(")
                    {
                        groupStack.Push(currentGroup);

                        var newGroup = new SelectWhereGroup();

                        currentGroup.Clauses.Add(newGroup);

                        currentGroup = newGroup;
                    }
                    else if (word == ")")
                    {
                        currentGroup = groupStack.Pop();
                    }
                    else if (word == "or")
                    {
                        var clauseOperator = new SelectWhereOperator(SelectWhereClauseOperatorEnum.Or);

                        currentGroup.Clauses.Add(clauseOperator);
                    }
                    else if (word == "and")
                    {
                        var clauseOperator = new SelectWhereOperator(SelectWhereClauseOperatorEnum.And);

                        currentGroup.Clauses.Add(clauseOperator);
                    }
                    else
                    {
                        clauseWords.Add(word);
                    }
                }

                ParseClauseWords(clauseWords, currentGroup);

                selectStatement.Where = currentGroup.Clauses;
            }

            return(results);
        }
Beispiel #5
0
        public TokenParserResults Parse(ParseArgs <SelectStatement> parseArgs)
        {
            var selectStatement = parseArgs.Statement;
            var args            = parseArgs.StatementArgs;
            var statementParser = parseArgs.StatementsParser;

            var results = new TokenParserResults();

            var words = ParserUtils.GetWords(args).ToList();

            var index = 0;

            if (words.Any())
            {
                if (words[0] == "top")
                {
                    if (words.Count >= 2)
                    {
                        var value = 0;

                        if (int.TryParse(words[1], out value))
                        {
                            selectStatement.Top = value;
                            index = 2;
                        }
                        else
                        {
                            results.Errors.Add(new SqlStatementError("Top expects a numerical value", 0));
                        }
                    }
                    else
                    {
                        results.Errors.Add(new SqlStatementError("Top without a numerical value", 0));
                    }
                }

                if (results.Errors.Any())
                {
                    return(results);
                }

                var columns = ParserUtils.SplitTokens(words.GetRange(index, words.Count - index));

                foreach (var wordList in columns)
                {
                    if (wordList.Any() == false)
                    {
                        results.Errors.Add(new SqlStatementError("No column specified", 0));

                        return(results);
                    }

                    SelectColumnBase selectColumn = null;

                    var startWord = wordList[0];

                    double number = 0;

                    if (startWord.IsQuoted() || double.TryParse(startWord, out number))
                    {
                        object value = startWord.IsQuoted()
                            ? startWord.CleanRaw()
                            : number.ToString();

                        var valueType = startWord.IsQuoted()
                            ? typeof(string)
                            : typeof(double);

                        if (startWord.IsQuoted() == false && startWord.IndexOf(".", StringComparison.Ordinal) < 0)
                        {
                            valueType = typeof(int);
                            value     = int.Parse(startWord);
                        }

                        if (wordList.Count > 3)
                        {
                            results.Errors.Add(new SqlStatementError("Unknown tokens", 0));

                            return(results);
                        }

                        if (wordList.Count == 3)
                        {
                            if (wordList[1] != "as")
                            {
                                results.Errors.Add(new SqlStatementError("Expecting 'As' keyword", 0));

                                return(results);
                            }

                            selectColumn = new RawSelectColumn(wordList[2], value)
                            {
                                ValueType = valueType
                            };
                        }
                        else if (wordList.Count == 2)
                        {
                            selectColumn = new RawSelectColumn(wordList[1], value)
                            {
                                ValueType = valueType
                            };
                        }
                        else
                        {
                            selectColumn = new RawSelectColumn(null, value)
                            {
                                ValueType = valueType
                            };
                        }
                    }
                    else if (startWord.StartsWith("*"))
                    {
                        if (wordList.Count > 1)
                        {
                            results.Errors.Add(new SqlStatementError("Found unsupported tokens after '*'", 0));

                            return(results);
                        }

                        selectColumn = new AllSelectColumn();
                    }
                    else if (startWord.StartsWith("+"))
                    {
                        if (wordList.Count > 1)
                        {
                            results.Errors.Add(new SqlStatementError("Found unsupported tokens after '+'", 0));

                            return(results);
                        }

                        selectColumn = new SystemSelectColumn();
                    }
                    else if (char.IsLetter(startWord[0]))
                    {
                        selectColumn = ParseColumn(wordList, results.Errors);
                    }
                    else if (startWord == "(")
                    {
                        var nextWord = wordList[1];

                        if (nextWord == "select")
                        {
                            var startIndex = 1;
                            var endIndex   = wordList.FindLastIndex(x => x == ")");
                            var innerSql   = string.Join(" ", wordList.GetRange(startIndex, endIndex - startIndex));

                            var statement = statementParser.ParseSelect(new SqlStatement()
                            {
                                Builder = new StringBuilder(innerSql)
                            });

                            if (statement.Errors.Any())
                            {
                                throw new Exception($"Unable to parse inner select statement '{innerSql}'");
                            }

                            var descTokenIndex = wordList.Count - 1;

                            var label = wordList[descTokenIndex];

                            descTokenIndex--;

                            if (wordList[descTokenIndex].NotIn(")", "as"))
                            {
                                throw new Exception($"Unexpected token after inner select '{innerSql}'");
                            }

                            if (wordList[descTokenIndex] == "as")
                            {
                                descTokenIndex--;
                            }

                            if (wordList[descTokenIndex] != ")")
                            {
                                throw new Exception($"Unexpected token after inner select '{innerSql}'");
                            }

                            selectColumn = new InnerSelectColumn(label, statement.Value);
                        }
                    }

                    if (selectColumn == null)
                    {
                        throw new NotSupportedException();
                    }

                    selectStatement.Columns.Add(selectColumn);
                }
            }

            return(results);
        }