Exemple #1
0
        private SelectColumnBase ParseColumn(List <string> wordList, List <SqlStatementError> errors)
        {
            var startWord      = wordList[0];
            var ascTokenIndex  = 0;
            var descTokenIndex = wordList.Count - 1;
            var nextToken      = wordList.Count > 1
                ? wordList[++ascTokenIndex]
                : null;

            if (nextToken == "(")
            {
                var functionName  = startWord;
                var functionLabel = "";

                if (wordList[descTokenIndex] == ")")
                {
                    functionLabel = startWord;
                    descTokenIndex--;
                }
                else
                {
                    functionLabel = wordList[descTokenIndex];

                    descTokenIndex--;

                    if (wordList[descTokenIndex].NotIn(")", "as"))
                    {
                        throw new Exception($"Unexpected token after function '{wordList[wordList.Count - 2]}'");
                    }

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

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

                var functionColumn = new SelectColumnFunction(functionName, functionLabel);

                var argList = wordList.GetRange(2, descTokenIndex - 1);

                var functionArgs = ParserUtils.SplitTokens(argList);

                foreach (var functionArg in functionArgs)
                {
                    functionColumn.Args.Add(ParseColumn(functionArg, errors));
                }

                return(functionColumn);
            }

            double           number       = 0;
            SelectColumnBase selectColumn = null;

            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)
                {
                    errors.Add(new SqlStatementError("Unknown tokens", 0));

                    return(null);
                }

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

                        return(null);
                    }

                    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
                    };
                }

                return(selectColumn);
            }

            if (char.IsLetter(startWord[0]))
            {
                if (wordList.Count > 3)
                {
                    errors.Add(new SqlStatementError("Unknown tokens", 0));

                    return(null);
                }

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

                        return(null);
                    }

                    selectColumn = new FieldSelectColumn(wordList[2], startWord);
                }
                else if (wordList.Count == 2)
                {
                    selectColumn = new FieldSelectColumn(wordList[1], startWord);
                }
                else
                {
                    selectColumn = new FieldSelectColumn(null, startWord);
                }

                return(selectColumn);
            }

            throw new Exception("Unexpected function arguments.");
        }
Exemple #2
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);
        }