private ResultSetBuilder VisitContains(SymbolContainsExpression exp)
        {
            var memberName = ExHelper.GetMemberName(exp.Match, _itemType, exp);
            var result     = new ResultSetBuilder(_journal, _tx);
            var vals       = ExHelper.GetLiteralValue(exp.Values, _parameters, exp);

            if (!(vals is IEnumerable))
            {
                throw QueryExceptionExtensions.ExpressionNotSupported(
                          string.Format("Parameter {0} does not implement IEnumerable.", exp.Values), exp);
            }

            try
            {
                result.IndexCollectionScan(memberName, (IEnumerable)vals, exp);
            }
            catch (InvalidCastException ex)
            {
                throw QueryExceptionExtensions.ExpressionNotSupported(
                          string.Format("Parameter {0} value of type '{1}' cannot be used in " +
                                        "IN statement with column '{2}'. {3}", exp.Values, vals.GetType(), memberName, ex.Message), exp);
            }

            return(result);
        }
        private ResultSetBuilder VisitOrderBy(OrderExpression exp)
        {
            var result    = Visit(exp.Body);
            var predicate = exp.Predicate;

            var lambda = predicate as LambdaExpression;

            if (lambda != null)
            {
                predicate = lambda.Body;
            }

            var member = ExHelper.GetMemberName(predicate, _itemType, exp);
            var column = _journal.Metadata.TryGetColumnByPropertyName(member);

            if (column == null)
            {
                throw QueryExceptionExtensions.ExpressionNotSupported(
                          string.Format("Column '{0}' does not exist", member), exp);
            }
            result.ApplyOrderBy(column, (EJournalExpressionType)exp.NodeType);
            return(result);
        }
        private ResultSetBuilder EvaluateEquals(Expression expression)
        {
            if (expression.NodeType == ExpressionType.Equal ||
                expression.NodeType == ExpressionType.NotEqual)
            {
                var literal    = ExHelper.GetLiteralValue(expression, _parameters);
                var memberName = ExHelper.GetMemberName(expression, _itemType);

                IColumnMetadata column;
                try
                {
                    column = _journal.Metadata.GetColumnByPropertyName(memberName);
                }
                catch (NFSdbConfigurationException)
                {
                    throw QueryExceptionExtensions.ExpressionNotSupported(
                              string.Format("Column {0} does not exist", memberName), expression);
                }

                if (_journal.Metadata.TimestampColumnID == column.ColumnID)
                {
                    if (expression.NodeType == ExpressionType.Equal)
                    {
                        if (literal is long || literal is DateTime)
                        {
                            if (GetTimestamp(_journal.Metadata) != null &&
                                GetTimestamp(_journal.Metadata).PropertyName == memberName)
                            {
                                DateInterval filterInterval;
                                if (literal is long)
                                {
                                    var timestamp = (long)literal;
                                    filterInterval = new DateInterval(DateUtils.UnixTimestampToDateTime(timestamp),
                                                                      DateUtils.UnixTimestampToDateTime(timestamp + 1));
                                }
                                else
                                {
                                    var timestamp = (DateTime)literal;
                                    filterInterval = new DateInterval(timestamp,
                                                                      new DateTime(timestamp.Ticks + 1, timestamp.Kind));
                                }

                                var result = new ResultSetBuilder(_journal, _tx);
                                result.TimestampInterval(filterInterval);
                                return(result);
                            }
                        }
                    }
                }

                var res = new ResultSetBuilder(_journal, _tx);
                try
                {
                    if (literal != null)
                    {
                        if (expression.NodeType == ExpressionType.Equal)
                        {
                            ReflectionHelper.CallStaticPrivateGeneric("CreateColumnScan", this,
                                                                      column.DataType.Clazz, column, literal, res);
                        }
                        else if (expression.NodeType == ExpressionType.NotEqual)
                        {
                            ReflectionHelper.CallStaticPrivateGeneric("CreateColumnNotEqualScan", this,
                                                                      column.DataType.Clazz, column, literal, res);
                        }
                    }
                    else
                    {
                        if (expression.NodeType == ExpressionType.Equal)
                        {
                            ReflectionHelper.CallStaticPrivateGeneric("CreateColumnScan", this,
                                                                      column.DataType.Clazz, column, null, res);
                        }
                        else if (expression.NodeType == ExpressionType.NotEqual)
                        {
                            ReflectionHelper.CallStaticPrivateGeneric("CreateColumnNotEqualScan", this,
                                                                      column.DataType.Clazz, column, null, res);
                        }
                    }
                }
                catch (NFSdbQueryableNotSupportedException ex)
                {
                    throw QueryExceptionExtensions.ExpressionNotSupported(ex.Message, expression);
                }
                catch (InvalidCastException ex)
                {
                    throw QueryExceptionExtensions.ExpressionNotSupported(ex.Message, expression);
                }
                return(res);
            }

            throw new NotSupportedException(
                      string.Format("Unable to translate expression {0} to journal operation", expression));
        }
        private ResultSetBuilder EvaluateCompare(Expression exp)
        {
            var memberName = ExHelper.GetMemberName(exp, _itemType);
            var literal    = ExHelper.GetLiteralValue(exp, _parameters);

            var columnMetadata = GetTimestamp(_journal.Metadata);

            if (columnMetadata != null &&
                string.Equals(columnMetadata.PropertyName, memberName, StringComparison.OrdinalIgnoreCase) &&
                (literal is long || literal is DateTime))
            {
                DateInterval filterInterval;
                var          nodeType = exp.NodeType;
                if (exp.GetLeft().NodeType == ExpressionType.Constant)
                {
                    nodeType = InvertComarison(nodeType);
                }

                switch (nodeType)
                {
                case ExpressionType.GreaterThan:
                    var timestamp = literal is long
                                    ?DateUtils.UnixTimestampToDateTime((long)literal + 1)
                                        : ((DateTime)literal).AddTicks(1);

                    filterInterval = DateInterval.From(timestamp);
                    break;

                case ExpressionType.GreaterThanOrEqual:
                    timestamp = literal is long
                                ?DateUtils.UnixTimestampToDateTime((long)literal)
                                    : (DateTime)literal;

                    filterInterval = DateInterval.From(timestamp);
                    break;

                case ExpressionType.LessThan:
                    timestamp = literal is long
                                ?DateUtils.UnixTimestampToDateTime((long)literal)
                                    : (DateTime)literal;

                    filterInterval = DateInterval.To(timestamp);
                    break;

                case ExpressionType.LessThanOrEqual:
                    timestamp = literal is long
                                ?DateUtils.UnixTimestampToDateTime((long)literal + 1)
                                    : ((DateTime)literal).AddTicks(1);

                    filterInterval = DateInterval.To(timestamp);
                    break;

                default:
                    throw QueryExceptionExtensions.ExpressionNotSupported(string.Format(
                                                                              "Timestamp column operation {0} is not supported. Supported operations are <, >, <=, >=",
                                                                              nodeType), exp);
                }

                var result = new ResultSetBuilder(_journal, _tx);
                result.TimestampInterval(filterInterval);
                return(result);
            }
            throw QueryExceptionExtensions.ExpressionNotSupported(
                      "Comparison is supported for timestamp column only. Unable to bind '{0} to journal query operation",
                      exp);
        }