public void ApplySelectPropertyFilter(QuerySelectProperty property, string filterText)
        {
            var filter = filterText?.Trim();

            if (string.IsNullOrWhiteSpace(filter))
            {
                // find and remove previous condition
            }
            else
            {
                // add new condition
                var filterOperator = "=";

                var operators = _resolver.GetCompareOperators();

                foreach (var o in operators)
                {
                    if (filter.StartsWith(o))
                    {
                        filterOperator = o;
                        filter         = filter.Substring(o.Count()).Trim();
                        break;
                    }
                }
                ;

                var  filterValue = filter;
                char quote       = _resolver.GetStringLiteralSymbol();

                if (filterValue.First() != '@' && (property.StoreProperty.Type == "String" || property.StoreProperty.Type == "DateTime"))
                {
                    if (filterValue.First() != quote)
                    {
                        filterValue = quote + filterValue;
                    }

                    if (filterValue.Last() != quote)
                    {
                        filterValue = filterValue + quote;
                    }
                }

                if (!string.IsNullOrWhiteSpace(SelectedQuery.WhereClause))
                {
                    SelectedQuery.WhereClause += " AND ";
                }

                SelectedQuery.WhereClause += $"{property.FromTable.Alias}.{property.StoreProperty.Name} {filterOperator} {filterValue}";
            }
        }
        // Read the next token from the input stream
        public void NextToken()
        {
            // Skip whitespace
            while (char.IsWhiteSpace(_currentChar))
            {
                NextChar();
            }

            if (_operators.Contains(_currentChar.ToString().ToLower()))
            {
                _currentToken = Token.Operator;
                var current = _currentChar.ToString();
                NextChar();
                Operator = current;
                return;
            }

            // Special characters
            switch (_currentChar)
            {
            case '\0':
                _currentToken = Token.EOF;
                return;

            //case '+':
            //    NextChar();
            //    _currentToken = Token.Add;
            //    return;

            //case '-':
            //    NextChar();
            //    _currentToken = Token.Subtract;
            //    return;

            //case '*':
            //    NextChar();
            //    _currentToken = Token.Multiply;
            //    return;

            //case '/':
            //    NextChar();
            //    _currentToken = Token.Divide;
            //    return;

            case '(':
                NextChar();
                _currentToken = Token.OpenParens;
                return;

            case ')':
                NextChar();
                _currentToken = Token.CloseParens;
                return;

            case ',':
                NextChar();
                _currentToken = Token.Comma;
                return;
            }

            // Number?
            if (char.IsDigit(_currentChar) || _currentChar == '.')
            {
                // Capture digits/decimal point
                var  sb = new StringBuilder();
                bool haveDecimalPoint = false;
                while (char.IsDigit(_currentChar) || (!haveDecimalPoint && _currentChar == '.'))
                {
                    sb.Append(_currentChar);
                    haveDecimalPoint = _currentChar == '.';
                    NextChar();
                }

                // Parse it
                Number        = decimal.Parse(sb.ToString(), CultureInfo.InvariantCulture);
                _currentToken = Token.Number;
                return;
            }

            // Field - starts with letter or underscore
            // also may be operator
            if (char.IsLetter(_currentChar) || _currentChar == '_')
            {
                var sb = new StringBuilder();

                // Accept letter, digit or underscore
                while (char.IsLetterOrDigit(_currentChar) || _currentChar == '_' || _currentChar == '.')
                {
                    sb.Append(_currentChar);
                    NextChar();
                }

                var sbs = sb.ToString();

                if (_operators.Contains(sbs.ToLower()))
                {
                    _currentToken = Token.Operator;
                    Operator      = sbs;
                    return;
                }

                // Setup token
                Field         = sbs;
                _currentToken = Token.Field;
                return;
            }

            // Param - starts with letter or underscore
            if (_currentChar == '@')
            {
                var sb = new StringBuilder();
                sb.Append(_currentChar);
                NextChar();

                // starts from letters and _
                if (char.IsLetter(_currentChar) || _currentChar == '_')
                {
                    sb.Append(_currentChar);
                    NextChar();
                }

                // Accept letter, digit or underscore
                while (char.IsLetterOrDigit(_currentChar) || _currentChar == '_')
                {
                    sb.Append(_currentChar);
                    NextChar();
                }

                // Setup token
                Param         = sb.ToString();
                _currentToken = Token.Param;
                return;
            }

            // string literal
            if (_currentChar == _resolver.GetStringLiteralSymbol())
            {
                var sb = new StringBuilder();
                NextChar();

                while (_currentChar != _resolver.GetStringLiteralSymbol())
                {
                    sb.Append(_currentChar);
                    NextChar();
                }

                NextChar();
                StringLiteral = sb.ToString();
                _currentToken = Token.StringLiteral;
                return;
            }


            throw new Exception($"Illigal literal '{_currentChar}'");
        }