public void Logical(ResultSetBuilder left, ResultSetBuilder right, ExpressionType op)
 {
     if (op == ExpressionType.And)
     {
         _planHead = OptimizeIntersect(left._planHead, right._planHead);
     }
     else if (op == ExpressionType.Or)
     {
         if (left._planHead is TimestampRangePlanItem &&
             right._planHead is TimestampRangePlanItem)
         {
             _planHead = left._planHead;
             _planHead.Timestamps.Union(right._planHead.Timestamps);
             return;
         }
         if (left._planHead is RowScanPlanItem && right._planHead is RowScanPlanItem)
         {
             var rowScan1 = (RowScanPlanItem)left._planHead;
             var rowScan2 = (RowScanPlanItem)right._planHead;
             if (rowScan1.TryUnion(rowScan2))
             {
                 _planHead = left.PlanItem;
                 return;
             }
         }
         _planHead = new UnionPlanItem(left._planHead, right._planHead);
     }
     else
     {
         throw new NotImplementedException();
     }
 }
        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 VisitSet(Expression left, Expression right, ExpressionType operation)
        {
            var res = new ResultSetBuilder(_journal, _tx);

            res.Logical(Visit(left), Visit(right), operation);
            return(res);
        }
        private ResultSetBuilder EvaluateLogical(Expression expression)
        {
            var left  = Visit(expression.GetLeft());
            var right = Visit(expression.GetRight());

            var result    = new ResultSetBuilder(_journal, _tx);
            var operation = expression.NodeType;

            if (operation == ExpressionType.AndAlso)
            {
                operation = ExpressionType.And;
            }

            if (operation == ExpressionType.OrElse)
            {
                operation = ExpressionType.Or;
            }

            result.Logical(left, right, operation);

            return(result);
        }
 public void ApplyFilter(ResultSetBuilder filter)
 {
     _planHead = OptimizeIntersect(_planHead, filter._planHead);
 }
 private static void CreateColumnNotEqualScan <TT>(IColumnMetadata column, object literal, ResultSetBuilder builder)
 {
     if (literal == null)
     {
         builder.ColumnNotNullScan(column);
     }
     else
     {
         var value  = (TT)column.ToTypedValue(literal);
         var lambda = (Func <TT, bool>)(t => !object.Equals(t, value));
         builder.ColumnLambdaScan(column, lambda);
     }
 }
 private static void CreateColumnScan <TT>(IColumnMetadata column, object literal, ResultSetBuilder builder)
 {
     if (literal == null)
     {
         builder.ColumnNullScan(column);
     }
     else
     {
         var value = (TT)column.ToTypedValue(literal);
         builder.ColumnScan <TT>(column, value);
     }
 }
        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);
        }