public void CanRemoveItemFromCacheWithDelegate()
        {
            var myObject1 = new TestCacheObject("test-1");
            var myObject2 = new TestCacheObject("bob");
            var myObject3 = new TestCacheObject("frank");

            CacheProvider.AddOrChangeValue(CacheKey.Create <string>("my-1"), myObject1);
            CacheProvider.AddOrChangeValue(CacheKey.Create <StrongClassKey>(x => x.MyName = "bob"), myObject2);
            CacheProvider.AddOrChangeValue(CacheKey.Create <StrongClassKey>(x => x.MyName = "frank"), myObject3);

            var resultFilterClause       = new ResultFilterClause(typeof(string), ResultFilterType.Any, 0);
            var fromClause               = new FromClause(HiveId.Empty.ToString(), HierarchyScope.AncestorsOrSelf, FixedStatusTypes.Published);
            var fieldPredicateExpression = new FieldPredicateExpression("title", ValuePredicateType.Equal, "blah");


            //var key = new HiveQueryCacheKey(new QueryDescription(resultFilterClause, fromClause, fieldPredicateExpression, Enumerable.Empty<SortClause>()));
            var key = CacheKey.Create(new HiveQueryCacheKey(new QueryDescription(resultFilterClause, fromClause, fieldPredicateExpression, Enumerable.Empty <SortClause>())));

            CacheProvider.AddOrChangeValue(key, myObject3);

            Assert.NotNull(CacheProvider.GetValue(CacheKey.Create <string>("my-1")));
            Assert.NotNull(CacheProvider.GetValue(CacheKey.Create <StrongClassKey>(x => x.MyName = "bob")));
            Assert.NotNull(CacheProvider.GetValue(CacheKey.Create <string>("my-1")));
            Assert.NotNull(CacheProvider.GetValue(key));

            CacheProvider.RemoveWhereKeyMatches <string>(x => x == "my-1");
            CacheProvider.RemoveWhereKeyMatches <StrongClassKey>(x => x.MyName == "bob");
            CacheProvider.RemoveWhereKeyMatches <HiveQueryCacheKey>(x => x.From.HierarchyScope == HierarchyScope.AncestorsOrSelf);

            Assert.Null(CacheProvider.Get(CacheKey.Create <string>("my-1")));
            Assert.Null(CacheProvider.GetValue(CacheKey.Create <string>("my-1")));
            Assert.Null(CacheProvider.Get(CacheKey.Create <StrongClassKey>(x => x.MyName    = "bob")));
            Assert.NotNull(CacheProvider.Get(CacheKey.Create <StrongClassKey>(x => x.MyName = "frank")));
        }
        private static object GetIdValue(FieldPredicateExpression node)
        {
            var idValue = node.ValueExpression.Type.IsAssignableFrom(typeof(HiveId))
                                 ? ((HiveId)node.ValueExpression.Value).Value.Value
                                 : node.ValueExpression.Value;

            return(idValue);
        }
Example #3
0
        private static Guid GetIdValue(FieldPredicateExpression node)
        {
            var idValue = Guid.Empty;

            if (node.ValueExpression.Type.IsAssignableFrom(typeof(HiveId)))
            {
                idValue = (Guid)((HiveId)node.ValueExpression.Value).Value;
            }
            else
            {
                Guid.TryParse(node.ValueExpression.Value.ToString(), out idValue);
            }
            return(idValue);
        }
        public void CanRemoveItemFromCacheWithDelegate()
        {
            var myObject1 = new TestCacheObject("test-1");
            var myObject2 = new TestCacheObject("bob");
            var myObject3 = new TestCacheObject("frank");

            CacheProvider.AddOrChangeValue(CacheKey.Create <string>("my-1"), myObject1);
            CacheProvider.AddOrChangeValue(CacheKey.Create <StrongClassKey>(x => x.MyName = "bob"), myObject2);
            CacheProvider.AddOrChangeValue(CacheKey.Create <StrongClassKey>(x => x.MyName = "frank"), myObject3);

            if (CacheIsAsync)
            {
                Thread.Sleep(500);
            }

            var resultFilterClause       = new ResultFilterClause(typeof(string), ResultFilterType.Any, 0);
            var scopeStartId             = new HiveId(Guid.NewGuid());
            var fromClause               = new FromClause(scopeStartId.AsEnumerableOfOne(), HierarchyScope.AncestorsOrSelf, FixedStatusTypes.Published);
            var fieldPredicateExpression = new FieldPredicateExpression("title", ValuePredicateType.Equal, "blah");


            //var key = new HiveQueryCacheKey(new QueryDescription(resultFilterClause, fromClause, fieldPredicateExpression, Enumerable.Empty<SortClause>()));
            var key = CacheKey.Create(new HiveQueryCacheKey(new QueryDescription(resultFilterClause, fromClause, fieldPredicateExpression, Enumerable.Empty <SortClause>())));

            CacheProvider.AddOrChangeValue(key, myObject3);

            if (CacheIsAsync)
            {
                Thread.Sleep(500);
            }

            Assert.NotNull(CacheProvider.GetValue <TestCacheObject>(CacheKey.Create <string>("my-1")));
            Assert.NotNull(CacheProvider.GetValue <TestCacheObject>(CacheKey.Create <StrongClassKey>(x => x.MyName = "bob")));
            Assert.NotNull(CacheProvider.GetValue <TestCacheObject>(CacheKey.Create <string>("my-1")));
            Assert.NotNull(CacheProvider.GetValue <TestCacheObject>(key));

            CacheProvider.RemoveWhereKeyMatches <string>(x => x == "my-1");
            CacheProvider.RemoveWhereKeyMatches <StrongClassKey>(x => x.MyName == "bob");
            CacheProvider.RemoveWhereKeyMatches <HiveQueryCacheKey>(x => x.From.HierarchyScope == HierarchyScope.AncestorsOrSelf);

            // No check for async as removals should be instant

            Assert.Null(CacheProvider.Get <TestCacheObject>(CacheKey.Create <string>("my-1")));
            Assert.Null(CacheProvider.GetValue <TestCacheObject>(CacheKey.Create <string>("my-1")));
            Assert.Null(CacheProvider.Get <TestCacheObject>(CacheKey.Create <StrongClassKey>(x => x.MyName    = "bob")));
            Assert.NotNull(CacheProvider.Get <TestCacheObject>(CacheKey.Create <StrongClassKey>(x => x.MyName = "frank")));
        }
Example #5
0
        public override Expression <Func <XElement, bool> > VisitFieldPredicate(FieldPredicateExpression node)
        {
            var fieldName  = node.SelectorExpression.FieldName;
            var fieldValue = node.ValueExpression.Value.ToString();

            // Normalise incoming field names
            switch (fieldName.ToLowerInvariant())
            {
            case "id":
                fieldName = "id";
                var value = string.Empty;
                if (node.ValueExpression.Type.IsAssignableFrom(typeof(HiveId)))
                {
                    value = ((HiveId)node.ValueExpression.Value).ToString(HiveIdFormatStyle.AutoSingleValue);
                }
                else
                {
                    value = node.ValueExpression.Value.ToString();
                }
                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    return(x => x.Attributes(fieldName).Any() && string.Equals((string)x.Attribute(fieldName), value, StringComparison.InvariantCultureIgnoreCase));

                case ValuePredicateType.NotEqual:
                    return(x => x.Attributes(fieldName).Any() && !string.Equals((string)x.Attribute(fieldName), value, StringComparison.InvariantCultureIgnoreCase));

                default:
                    throw new InvalidOperationException("Cannot query an item by id by any other method than Equals or NotEquals");
                }
            }

            switch (node.ValueExpression.ClauseType)
            {
            case ValuePredicateType.Equal:
                return(x => x.Attributes(fieldName).Any() && string.Equals((string)x.Attribute(fieldName), fieldValue, StringComparison.InvariantCultureIgnoreCase));

            case ValuePredicateType.EndsWith:
                return(x => x.Attributes(fieldName).Any() && ((string)x.Attribute(fieldName)).EndsWith(fieldValue, StringComparison.InvariantCultureIgnoreCase));
            }

            // Only get here if the query has something we don't support
            return(x => false);
        }
Example #6
0
        public void HiveQueryCacheKeyToFromJson()
        {
            var guid  = Guid.NewGuid();
            var guid2 = Guid.NewGuid();
            var guid3 = Guid.NewGuid();
            var resultFilterClause        = new ResultFilterClause(typeof(string), ResultFilterType.Any, 0);
            var hiveId                    = new HiveId(guid);
            var expected                  = new HiveId(guid2);
            var fullHiveId                = new HiveId(new Uri("content://blah/"), "nhibernate", new HiveIdValue(guid3));
            var scopeStartId              = new HiveId(Guid.NewGuid());
            var fromClause                = new FromClause(scopeStartId.AsEnumerableOfOne(), HierarchyScope.AncestorsOrSelf, FixedStatusTypes.Published, "default-type", new[] { hiveId, expected, fullHiveId });
            var fieldPredicateExpression  = new FieldPredicateExpression("title", ValuePredicateType.Equal, "blah");
            var fieldPredicateExpression2 = new FieldPredicateExpression("title", ValuePredicateType.Equal, "blah");
            var binary                    = Expression.MakeBinary(ExpressionType.ExclusiveOr, fieldPredicateExpression, fieldPredicateExpression2);
            var aSortClause               = new SortClause(new FieldSelectorExpression("tag"), SortDirection.Descending, 2);

            //var key = new HiveQueryCacheKey(new QueryDescription(resultFilterClause, fromClause, fieldPredicateExpression, Enumerable.Empty<SortClause>()));
            var key     = CacheKey.Create(new HiveQueryCacheKey(new QueryDescription(resultFilterClause, fromClause, fieldPredicateExpression, aSortClause.AsEnumerableOfOne())));
            var keyJson = key.ToJson();
            var keyBack = (CacheKey <HiveQueryCacheKey>)keyJson;

            // var keyJsonTwice = keyBack.ToJson();
            Assert.That(keyBack, Is.Not.Null);
            //Assert.That(keyJson, Is.EqualTo(keyJsonTwice));
            //NOTE: Criteria does not deserialize at the moment, but caching implementation should find matching keys OK still if it maintains an inner collection of original key objects if (key.Original.Criteria != null) Assert.That(keyBack.Original.Criteria, Is.Not.Null);
            Assert.True(keyBack.Original.ResultFilters.Any());
            Assert.That(keyBack.Original.ResultFilters.First().ResultType, Is.EqualTo(typeof(string)));
            Assert.That(keyBack.Original.SortClauses.Count(), Is.EqualTo(key.Original.SortClauses.Count()));
            Assert.That(keyBack.Original.SortClauses.FirstOrDefault().Direction, Is.EqualTo(SortDirection.Descending));
            Assert.That(keyBack.Original.SortClauses.FirstOrDefault().Priority, Is.EqualTo(2));
            Assert.That(keyBack.Original.From.HierarchyScope, Is.EqualTo(key.Original.From.HierarchyScope));
            Assert.That(keyBack.Original.From.RequiredEntityIds.Count(), Is.EqualTo(3));
            Assert.That(keyBack.Original.From.RequiredEntityIds.FirstOrDefault(), Is.EqualTo(hiveId));
            Assert.That(keyBack.Original.From.RequiredEntityIds.FirstOrDefault().Value.Type, Is.EqualTo(HiveIdValueTypes.Guid));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(1), Is.EqualTo(expected));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(1).Value.Type, Is.EqualTo(HiveIdValueTypes.Guid));

            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(2), Is.EqualTo(fullHiveId));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(2).Value.Type, Is.EqualTo(HiveIdValueTypes.Guid));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(2).ProviderId, Is.EqualTo("nhibernate"));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(2).ProviderGroupRoot.ToString(), Is.EqualTo(fullHiveId.ProviderGroupRoot.ToString()));
        }
        /// <summary>
        /// Negates a field predicate, i.e. reverses its <see cref="ValuePredicateType"/> for example Equals will be switched to NotEquals.
        /// </summary>
        /// <param name="fieldPredicateExpression">The field predicate expression.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static FieldPredicateExpression NegateFieldPredicate(FieldPredicateExpression fieldPredicateExpression)
        {
            Func<ValuePredicateType> reversed = () =>
                {
                    switch (fieldPredicateExpression.ValueExpression.ClauseType)
                    {
                        case ValuePredicateType.Equal:
                            return ValuePredicateType.NotEqual;
                        case ValuePredicateType.GreaterThan:
                            return ValuePredicateType.LessThan;
                        case ValuePredicateType.GreaterThanOrEqual:
                            return ValuePredicateType.LessThanOrEqual;
                        case ValuePredicateType.NotEqual:
                            return ValuePredicateType.Equal;
                    }
                    return fieldPredicateExpression.ValueExpression.ClauseType;
                };

            return new FieldPredicateExpression(fieldPredicateExpression.SelectorExpression, new FieldValueExpression(reversed.Invoke(), fieldPredicateExpression.ValueExpression.Value));
        }
Example #8
0
        public override Expression VisitFieldPredicate(FieldPredicateExpression node)
        {
            if (node.SelectorExpression == null)
            {
                _expressionsFound.Append("(SelectorExpression == null)");
                return(node);
            }

            _expressionsFound.AppendFormat("\nField: {0} {1} {2}", node.SelectorExpression.FieldName, node.ValueExpression.ClauseType.ToString(), node.ValueExpression.Value);

            if (node.SelectorExpression.FieldName == _fieldName && node.ValueExpression.Value.Equals(_fieldValue) && node.ValueExpression.ClauseType == _valuePredicateType)
            {
                if ((_subFieldName != null && node.SelectorExpression.ValueKey == _subFieldName) || _subFieldName == null)
                {
                    FoundMatch = true;
                }
            }

            return(node);
        }
        public void HiveQueryCacheKeyToFromJson()
        {
            var guid = Guid.NewGuid();
            var guid2 = Guid.NewGuid();
            var guid3 = Guid.NewGuid();
            var resultFilterClause = new ResultFilterClause(typeof(string), ResultFilterType.Any, 0);
            var hiveId = new HiveId(guid);
            var expected = new HiveId(guid2);
            var fullHiveId = new HiveId(new Uri("content://blah/"), "nhibernate", new HiveIdValue(guid3));
            var scopeStartId = new HiveId(Guid.NewGuid());
            var fromClause = new FromClause(scopeStartId.AsEnumerableOfOne(), HierarchyScope.AncestorsOrSelf, FixedStatusTypes.Published, "default-type", new[] { hiveId, expected, fullHiveId });
            var fieldPredicateExpression = new FieldPredicateExpression("title", ValuePredicateType.Equal, "blah");
            var fieldPredicateExpression2 = new FieldPredicateExpression("title", ValuePredicateType.Equal, "blah");
            var binary = Expression.MakeBinary(ExpressionType.ExclusiveOr, fieldPredicateExpression, fieldPredicateExpression2);
            var aSortClause = new SortClause(new FieldSelectorExpression("tag"), SortDirection.Descending, 2);

            //var key = new HiveQueryCacheKey(new QueryDescription(resultFilterClause, fromClause, fieldPredicateExpression, Enumerable.Empty<SortClause>()));
            var key = CacheKey.Create(new HiveQueryCacheKey(new QueryDescription(resultFilterClause, fromClause, fieldPredicateExpression, aSortClause.AsEnumerableOfOne())));
            var keyJson = key.ToJson();
            var keyBack = (CacheKey<HiveQueryCacheKey>)keyJson;
           // var keyJsonTwice = keyBack.ToJson();
            Assert.That(keyBack, Is.Not.Null);
            //Assert.That(keyJson, Is.EqualTo(keyJsonTwice));
            //NOTE: Criteria does not deserialize at the moment, but caching implementation should find matching keys OK still if it maintains an inner collection of original key objects if (key.Original.Criteria != null) Assert.That(keyBack.Original.Criteria, Is.Not.Null);
            Assert.True(keyBack.Original.ResultFilters.Any());
            Assert.That(keyBack.Original.ResultFilters.First().ResultType, Is.EqualTo(typeof(string)));
            Assert.That(keyBack.Original.SortClauses.Count(), Is.EqualTo(key.Original.SortClauses.Count()));
            Assert.That(keyBack.Original.SortClauses.FirstOrDefault().Direction, Is.EqualTo(SortDirection.Descending));
            Assert.That(keyBack.Original.SortClauses.FirstOrDefault().Priority, Is.EqualTo(2));
            Assert.That(keyBack.Original.From.HierarchyScope, Is.EqualTo(key.Original.From.HierarchyScope));
            Assert.That(keyBack.Original.From.RequiredEntityIds.Count(), Is.EqualTo(3));
            Assert.That(keyBack.Original.From.RequiredEntityIds.FirstOrDefault(), Is.EqualTo(hiveId));
            Assert.That(keyBack.Original.From.RequiredEntityIds.FirstOrDefault().Value.Type, Is.EqualTo(HiveIdValueTypes.Guid));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(1), Is.EqualTo(expected));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(1).Value.Type, Is.EqualTo(HiveIdValueTypes.Guid));

            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(2), Is.EqualTo(fullHiveId));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(2).Value.Type, Is.EqualTo(HiveIdValueTypes.Guid));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(2).ProviderId, Is.EqualTo("nhibernate"));
            Assert.That(keyBack.Original.From.RequiredEntityIds.ElementAt(2).ProviderGroupRoot.ToString(), Is.EqualTo(fullHiveId.ProviderGroupRoot.ToString()));
        }
        public override Expression VisitFieldPredicate(FieldPredicateExpression node)
        {
            _expressionsFound.AppendFormat("\n{0}", node);

            foreach (var fieldPredicateExpression in _tester.Fields)
            {
                if (node.SelectorExpression.FieldName == fieldPredicateExpression.SelectorExpression.FieldName &&
                    node.ValueExpression.Value.Equals(fieldPredicateExpression.ValueExpression.Value) &&
                    node.ValueExpression.ClauseType == fieldPredicateExpression.ValueExpression.ClauseType)
                {
                    if ((fieldPredicateExpression.SelectorExpression.ValueKey != null && node.SelectorExpression.ValueKey == fieldPredicateExpression.SelectorExpression.ValueKey) ||
                        fieldPredicateExpression.SelectorExpression.ValueKey == null)
                    {
                        FoundMatch = true;
                        break;
                    }
                }
            }

            return(node);
        }
        /// <summary>
        /// Negates a field predicate, i.e. reverses its <see cref="ValuePredicateType"/> for example Equals will be switched to NotEquals.
        /// </summary>
        /// <param name="fieldPredicateExpression">The field predicate expression.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static FieldPredicateExpression NegateFieldPredicate(FieldPredicateExpression fieldPredicateExpression)
        {
            Func <ValuePredicateType> reversed = () =>
            {
                switch (fieldPredicateExpression.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    return(ValuePredicateType.NotEqual);

                case ValuePredicateType.GreaterThan:
                    return(ValuePredicateType.LessThan);

                case ValuePredicateType.GreaterThanOrEqual:
                    return(ValuePredicateType.LessThanOrEqual);

                case ValuePredicateType.NotEqual:
                    return(ValuePredicateType.Equal);
                }
                return(fieldPredicateExpression.ValueExpression.ClauseType);
            };

            return(new FieldPredicateExpression(fieldPredicateExpression.SelectorExpression, new FieldValueExpression(reversed.Invoke(), fieldPredicateExpression.ValueExpression.Value)));
        }
        public override MembershipProviderQuery VisitFieldPredicate(FieldPredicateExpression node)
        {
            var fieldName  = node.SelectorExpression.FieldName;
            var valueKey   = node.SelectorExpression.ValueKey;
            var fieldValue = node.ValueExpression.Value.ToString();

            switch (fieldName.ToLowerInvariant())
            {
            case "id":
                var idValue = GetIdValue(node);

                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    return(new MembershipProviderQuery(MembershipQueryType.ById, idValue));

                case ValuePredicateType.NotEqual:
                    Func <IEnumerable <MembershipUser>, IEnumerable <MembershipUser> > filter = x => x.Where(m => m.ProviderUserKey != idValue);
                    return(new MembershipProviderQuery(MembershipQueryType.Custom, filter));

                default:
                    throw new InvalidOperationException(
                              "Cannot query an item by id by any other operator than == or !=");
                }
            }

            if (!valueKey.IsNullOrWhiteSpace())
            {
                throw new NotImplementedException();
            }

            //now, select the field value....
            switch (node.ValueExpression.ClauseType)
            {
            case ValuePredicateType.Equal:
                if (fieldName.InvariantEquals(MemberSchema.EmailAlias))
                {
                    return(new MembershipProviderQuery(MembershipQueryType.ByEmail, fieldValue));
                }
                if (fieldName.InvariantEquals(MemberSchema.UsernameAlias))
                {
                    return(new MembershipProviderQuery(MembershipQueryType.ByUsername, fieldValue));
                }
                throw new NotSupportedException("The Membership wrapper Hive provider does not support querying fields other than Email and Username");

            case ValuePredicateType.NotEqual:
                if (fieldName.InvariantEquals(MemberSchema.EmailAlias))
                {
                    Func <IEnumerable <MembershipUser>, IEnumerable <MembershipUser> > filter = x => x.Where(m => m.Email != fieldValue);
                    return(new MembershipProviderQuery(MembershipQueryType.Custom, filter));
                }
                if (fieldName.InvariantEquals(MemberSchema.UsernameAlias))
                {
                    Func <IEnumerable <MembershipUser>, IEnumerable <MembershipUser> > filter = x => x.Where(m => m.UserName != fieldValue);
                    return(new MembershipProviderQuery(MembershipQueryType.Custom, filter));
                }
                throw new NotSupportedException("The Membership wrapper Hive provider does not support querying fields other than Email and Username");

            case ValuePredicateType.MatchesWildcard:
            case ValuePredicateType.Contains:
                if (fieldName.InvariantEquals(MemberSchema.EmailAlias))
                {
                    return(new MembershipProviderQuery(MembershipQueryType.ByEmail, fieldValue, ValuePredicateType.Contains));
                }
                if (fieldName.InvariantEquals(MemberSchema.UsernameAlias))
                {
                    return(new MembershipProviderQuery(MembershipQueryType.ByUsername, fieldValue, ValuePredicateType.Contains));
                }
                throw new NotSupportedException("The Membership wrapper Hive provider does not support querying fields other than Email and Username");

            case ValuePredicateType.StartsWith:
                if (fieldName.InvariantEquals(MemberSchema.EmailAlias))
                {
                    return(new MembershipProviderQuery(MembershipQueryType.ByEmail, fieldValue, ValuePredicateType.StartsWith));
                }
                if (fieldName.InvariantEquals(MemberSchema.UsernameAlias))
                {
                    return(new MembershipProviderQuery(MembershipQueryType.ByUsername, fieldValue, ValuePredicateType.StartsWith));
                }
                throw new NotSupportedException("The Membership wrapper Hive provider does not support querying fields other than Email and Username");

            case ValuePredicateType.EndsWith:
                if (fieldName.InvariantEquals(MemberSchema.EmailAlias))
                {
                    return(new MembershipProviderQuery(MembershipQueryType.ByEmail, fieldValue, ValuePredicateType.EndsWith));
                }
                if (fieldName.InvariantEquals(MemberSchema.UsernameAlias))
                {
                    return(new MembershipProviderQuery(MembershipQueryType.ByUsername, fieldValue, ValuePredicateType.EndsWith));
                }
                throw new NotSupportedException("The Membership wrapper Hive provider does not support querying fields other than Email and Username");

            default:
                throw new InvalidOperationException(
                          "This linq provider doesn't support a ClauseType of {0} for field {1}".InvariantFormat(
                              node.ValueExpression.ClauseType.ToString(), fieldName));
            }
        }
        public override QueryOver <NodeVersion> VisitFieldPredicate(FieldPredicateExpression node)
        {
            var fieldName  = node.SelectorExpression.FieldName;
            var valueKey   = node.SelectorExpression.ValueKey;
            var fieldValue = node.ValueExpression.Value;

            switch (fieldName.ToLowerInvariant())
            {
            case "id":
                Guid idValue = GetIdValue(node);

                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    return(QueryOver.Of <NodeVersion>().Where(x => x.Node.Id == idValue).Select(x => x.Id));

                case ValuePredicateType.NotEqual:
                    return(QueryOver.Of <NodeVersion>().Where(x => x.Node.Id != idValue).Select(x => x.Id));;

                default:
                    throw new InvalidOperationException(
                              "Cannot query an item by id by any other operator than == or !=");
                }
            }

            NodeVersion              aliasNodeVersion         = null;
            Attribute                aliasAttribute           = null;
            AttributeDefinition      aliasAttributeDefinition = null;
            AttributeStringValue     aliasStringValue         = null;
            AttributeLongStringValue aliasLongStringValue     = null;
            NodeRelation             aliasNodeRelation        = null;
            AttributeDateValue       aliasDateValue           = null;

            //TODO: This is going to need to lookup more than string values

            var queryString = QueryOver.Of <NodeVersion>(() => aliasNodeVersion)
                              .JoinQueryOver <Attribute>(() => aliasNodeVersion.Attributes, () => aliasAttribute)
                              .JoinQueryOver <AttributeDefinition>(() => aliasAttribute.AttributeDefinition, () => aliasAttributeDefinition)
                              .Left.JoinQueryOver <AttributeStringValue>(() => aliasAttribute.AttributeStringValues, () => aliasStringValue)
                              .Left.JoinQueryOver <AttributeLongStringValue>(() => aliasAttribute.AttributeLongStringValues, () => aliasLongStringValue)
                              .Left.JoinQueryOver(() => aliasAttribute.AttributeDateValues, () => aliasDateValue)
                              //select the field name...
                              .Where(x => aliasAttributeDefinition.Alias == fieldName);

            if (!valueKey.IsNullOrWhiteSpace())
            {
                //if the value key is specified, then add that to the query
                queryString = queryString.And(() => aliasStringValue.ValueKey == valueKey || aliasLongStringValue.ValueKey == valueKey).Select(x => x.Id);
            }


            //now, select the field value....
            switch (node.ValueExpression.ClauseType)
            {
            case ValuePredicateType.Equal:
                var sqlCeCompatibleQuery =
                    Restrictions.Or(
                        Restrictions.Eq(
                            Projections.Property <AttributeStringValue>(x => aliasStringValue.Value), fieldValue),
                        Restrictions.Like(
                            Projections.Property <AttributeLongStringValue>(x => aliasLongStringValue.Value),
                            fieldValue as string,
                            MatchMode.Exact));

                return(queryString.And(sqlCeCompatibleQuery).Select(x => x.Id));

            case ValuePredicateType.NotEqual:
                return(queryString.And(x => aliasStringValue.Value != fieldValue).Select(x => x.Id));

            case ValuePredicateType.MatchesWildcard:
            case ValuePredicateType.Contains:
                return(queryString.And(Restrictions.Like(Projections.Property <AttributeStringValue>(x => aliasStringValue.Value), fieldValue as string, MatchMode.Anywhere)).Select(x => x.Id));

            case ValuePredicateType.StartsWith:
                return(queryString.And(Restrictions.Like(Projections.Property <AttributeStringValue>(x => aliasStringValue.Value), fieldValue as string, MatchMode.Start)).Select(x => x.Id));

            case ValuePredicateType.EndsWith:
                return(queryString.And(Restrictions.Like(Projections.Property <AttributeStringValue>(x => aliasStringValue.Value), fieldValue as string, MatchMode.End)).Select(x => x.Id));

            case ValuePredicateType.LessThanOrEqual:
                return
                    (queryString.And(
                         Restrictions.Le(Projections.Property <AttributeDateValue>(x => aliasDateValue.Value),
                                         (DateTimeOffset)fieldValue)));

            case ValuePredicateType.GreaterThanOrEqual:
                return
                    (queryString.And(
                         Restrictions.Ge(Projections.Property <AttributeDateValue>(x => aliasDateValue.Value),
                                         (DateTimeOffset)fieldValue)));

            default:
                throw new InvalidOperationException(
                          "This linq provider doesn't support a ClauseType of {0} for field {1}".InvariantFormat(
                              node.ValueExpression.ClauseType.ToString(), fieldName));
            }
        }
Example #14
0
 public abstract T VisitFieldPredicate(FieldPredicateExpression node);
Example #15
0
        public override QueryOver <NodeVersion> VisitFieldPredicate(FieldPredicateExpression node)
        {
            var fieldName      = node.SelectorExpression.FieldName;
            var valueKey       = node.SelectorExpression.ValueKey;
            var fieldValue     = node.ValueExpression.Value;
            var fieldValueType = fieldValue != null?fieldValue.GetType() : typeof(string);

            switch (fieldName.ToLowerInvariant())
            {
            case "id":
                Guid idValue = GetIdValue(node);

                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    return(QueryOver.Of <NodeVersion>().Where(x => x.Node.Id == idValue).Select(x => x.Id));

                case ValuePredicateType.NotEqual:
                    return(QueryOver.Of <NodeVersion>().Where(x => x.Node.Id != idValue).Select(x => x.Id));;

                default:
                    throw new InvalidOperationException(
                              "Cannot query an item by id by any other operator than == or !=");
                }
            }

            // First look up the types of the main field
            AttributeDefinition defAlias  = null;
            AttributeType       typeAlias = null;
            var attributeType             = _activeSession.QueryOver <AttributeDefinition>(() => defAlias)
                                            .JoinAlias(() => defAlias.AttributeType, () => typeAlias)
                                            .Where(() => defAlias.Alias == fieldName)
                                            .Select(x => typeAlias.PersistenceTypeProvider)
                                            .List <string>();

            var typesAlreadyEstablished = new List <string>();
            var typesToQuery            = new List <DataSerializationTypes>();

            foreach (var type in attributeType)
            {
                var typeName = type;
                if (typesAlreadyEstablished.Contains(typeName))
                {
                    continue;
                }
                try
                {
                    typesAlreadyEstablished.Add(typeName);
                    var persisterType = Type.GetType(typeName, false);
                    if (persisterType != null)
                    {
                        var persisterInstance = Activator.CreateInstance(persisterType) as IAttributeSerializationDefinition;
                        if (persisterInstance != null)
                        {
                            typesToQuery.Add(persisterInstance.DataSerializationType);
                        }
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }

            // U5-789
            // Workaround pending a better check of what data is actually saved
            // An issue arose because previous data had been saved in long-string,
            // but the datatype changed to be just string, therefore only string was
            // being queried despite all the data residing still in long-string
            if (typesToQuery.Contains(DataSerializationTypes.String) && !typesToQuery.Contains(DataSerializationTypes.LongString))
            {
                typesToQuery.Add(DataSerializationTypes.LongString);
            }

            NodeVersion              aliasNodeVersion         = null;
            Attribute                aliasAttribute           = null;
            AttributeDefinition      aliasAttributeDefinition = null;
            AttributeStringValue     aliasStringValue         = null;
            AttributeLongStringValue aliasLongStringValue     = null;
            AttributeIntegerValue    aliasIntegerValue        = null;
            AttributeDecimalValue    aliasDecimalValue        = null;
            NodeRelation             aliasNodeRelation        = null;
            AttributeDateValue       aliasDateValue           = null;

            QueryOver <NodeVersion, AttributeDefinition> queryExtender = QueryOver.Of <NodeVersion>(() => aliasNodeVersion)
                                                                         .JoinQueryOver <Attribute>(() => aliasNodeVersion.Attributes, () => aliasAttribute)
                                                                         .JoinQueryOver <AttributeDefinition>(() => aliasAttribute.AttributeDefinition, () => aliasAttributeDefinition);

            int numberOfMatchesEvaluated         = 0;
            AbstractCriterion restrictionBuilder = null;

            foreach (var dataSerializationTypese in typesToQuery.Distinct())
            {
                AbstractCriterion           restriction        = null;
                Expression <Func <object> > propertyExpression = null;
                Expression <Func <object> > subkeyExpression   = null;
                List <ValuePredicateType>   validClauseTypes   = null;
                var useLikeMatchForStrings = false;
                switch (dataSerializationTypese)
                {
                case DataSerializationTypes.SmallInt:
                case DataSerializationTypes.LargeInt:
                case DataSerializationTypes.Boolean:
                    queryExtender      = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeIntegerValues, () => aliasIntegerValue);
                    propertyExpression = () => aliasIntegerValue.Value;
                    subkeyExpression   = () => aliasIntegerValue.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.GreaterThan,
                        ValuePredicateType.GreaterThanOrEqual,
                        ValuePredicateType.LessThan,
                        ValuePredicateType.LessThanOrEqual,
                        ValuePredicateType.NotEqual
                    };
                    break;

                case DataSerializationTypes.Decimal:
                    queryExtender      = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeDecimalValues, () => aliasDecimalValue);
                    propertyExpression = () => aliasDecimalValue.Value;
                    subkeyExpression   = () => aliasDecimalValue.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.GreaterThan,
                        ValuePredicateType.GreaterThanOrEqual,
                        ValuePredicateType.LessThan,
                        ValuePredicateType.LessThanOrEqual,
                        ValuePredicateType.NotEqual
                    };
                    break;

                case DataSerializationTypes.String:
                    queryExtender      = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeStringValues, () => aliasStringValue);
                    propertyExpression = () => aliasStringValue.Value;
                    subkeyExpression   = () => aliasStringValue.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.NotEqual,
                        ValuePredicateType.Contains,
                        ValuePredicateType.StartsWith,
                        ValuePredicateType.EndsWith,
                        ValuePredicateType.MatchesWildcard
                    };
                    break;

                case DataSerializationTypes.LongString:
                    queryExtender          = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeLongStringValues, () => aliasLongStringValue);
                    propertyExpression     = () => aliasLongStringValue.Value;
                    subkeyExpression       = () => aliasLongStringValue.ValueKey;
                    useLikeMatchForStrings = true;
                    validClauseTypes       = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.NotEqual,
                        ValuePredicateType.Contains,
                        ValuePredicateType.StartsWith,
                        ValuePredicateType.EndsWith,
                        ValuePredicateType.MatchesWildcard
                    };
                    break;

                case DataSerializationTypes.Date:
                    queryExtender      = queryExtender.Left.JoinAlias(() => aliasAttribute.AttributeDateValues, () => aliasDateValue);
                    propertyExpression = () => aliasDateValue.Value;
                    subkeyExpression   = () => aliasDateValue.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.GreaterThan,
                        ValuePredicateType.GreaterThanOrEqual,
                        ValuePredicateType.LessThan,
                        ValuePredicateType.LessThanOrEqual,
                        ValuePredicateType.NotEqual,
                        ValuePredicateType.Empty
                    };
                    break;
                }

                if (!validClauseTypes.Contains(node.ValueExpression.ClauseType))
                {
                    throw new InvalidOperationException("A field of type {0} cannot be queried with operator {1}".InvariantFormat(dataSerializationTypese.ToString(), node.ValueExpression.ClauseType.ToString()));
                }

                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    restriction = GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression, subkeyExpression, valueKey);
                    break;

                case ValuePredicateType.NotEqual:
                    restriction = !GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression);
                    break;

                case ValuePredicateType.LessThan:
                    restriction = GetRestrictionLt(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.LessThanOrEqual:
                    restriction = GetRestrictionLtEq(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.GreaterThan:
                    restriction = GetRestrictionGt(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.GreaterThanOrEqual:
                    restriction = GetRestrictionGtEq(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.Contains:
                    restriction = GetRestrictionContains(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.StartsWith:
                    restriction = GetRestrictionStarts(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.EndsWith:
                    restriction = GetRestrictionEnds(fieldValue, propertyExpression);
                    break;
                }

                if (restriction != null)
                {
                    if (numberOfMatchesEvaluated == 0)
                    {
                        restrictionBuilder = restriction;
                        numberOfMatchesEvaluated++;
                    }
                    else
                    {
                        restrictionBuilder = Restrictions.Or(restriction, restrictionBuilder);
                    }
                }
            }

            if (restrictionBuilder != null)
            {
                queryExtender = queryExtender.Where(restrictionBuilder);
            }

            queryExtender = queryExtender
                            .And(x => aliasAttributeDefinition.Alias == fieldName);

            return(queryExtender.Select(x => x.Id));
        }
Example #16
0
        public void BooleanEquals()
        {
            var lookForPredicate = new FieldPredicateExpression("isTrue", ValuePredicateType.Equal, true);

            Run(GetQueryBooleanEquals("isTrue", true).WithField(lookForPredicate));
        }
        public override ICriterion VisitFieldPredicate(FieldPredicateExpression node)
        {
            var fieldName      = node.SelectorExpression.FieldName;
            var valueKey       = node.SelectorExpression.ValueKey;
            var fieldValue     = node.ValueExpression.Value;
            var fieldValueType = fieldValue != null?fieldValue.GetType() : typeof(string);

            switch (fieldName.ToLowerInvariant())
            {
            case "utccreated":
                var dateValue = (DateTimeOffset)fieldValue;
                if (dateValue == default(DateTimeOffset))
                {
                    break;
                }
                _requiresOuterNodeJoin = true;
                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.LessThanOrEqual:
                    return(Restrictions.Le(Projections.Property(() => outerNode.DateCreated), dateValue));
                }
                break;

            case "id":
                Guid idValue = GetIdValue(node);

                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    _discoveredRequiredNodeIds.Add(idValue);
                    return(Restrictions.Eq(Projections.Property(() => version.Node.Id), idValue));

                case ValuePredicateType.NotEqual:
                    _negatingNodeIdsExist = true;
                    return(!Restrictions.Eq(Projections.Property(() => version.Node.Id), idValue));

                default:
                    throw new InvalidOperationException(
                              "Cannot query an item by id by any other operator than == or !=");
                }

            case "system-internal-selected-template":
                //TODO Pending property editors getting involved in query modification prior to being passed to hive provider,
                //manually check for queries against a template here
                if (valueKey == "TemplateId" && fieldValue != null)
                {
                    var tryParseResult = HiveId.TryParse(fieldValue.ToString());
                    if (!tryParseResult.Success || tryParseResult.Result.ProviderGroupRoot == null || tryParseResult.Result.ProviderId == null ||
                        (tryParseResult.Result.ProviderGroupRoot.AbsoluteUri != "storage://" && tryParseResult.Result.ProviderId != "templates"))
                    {
                        var normalisedFieldValue = "/" + fieldValue.ToString().TrimStart("/").TrimEnd(".") + ".";
                        // Need to convert the value into the serialized form that a HiveId would use
                        var newValue = new HiveId("storage", "templates", new HiveIdValue(normalisedFieldValue)).ToString(HiveIdFormatStyle.UriSafe);
                        fieldValue = newValue;
                    }
                    else
                    {
                        fieldValue = tryParseResult.Result.ToString(HiveIdFormatStyle.UriSafe);
                    }
                }
                break;
            }

            // First look up the types of the main field
            AttributeDefinition defAlias  = null;
            AttributeType       typeAlias = null;
            var attributeType             = _activeSession.NhSession.QueryOver <AttributeDefinition>(() => defAlias)
                                            .JoinAlias(() => defAlias.AttributeType, () => typeAlias)
                                            .Where(() => defAlias.Alias == fieldName)
                                            .Select(x => typeAlias.PersistenceTypeProvider)
                                            .List <string>();

            foreach (var type in attributeType)
            {
                var typeName = type;
                if (_typesAlreadyEstablished.Contains(typeName))
                {
                    continue;
                }
                try
                {
                    _typesAlreadyEstablished.Add(typeName);
                    var persisterType = Type.GetType(typeName, false);
                    if (persisterType != null)
                    {
                        var persisterInstance = Activator.CreateInstance(persisterType) as IAttributeSerializationDefinition;
                        if (persisterInstance != null && !_typesToQuery.Contains(persisterInstance.DataSerializationType))
                        {
                            _typesToQuery.Add(persisterInstance.DataSerializationType);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error <NhCriteriaVisitor>("Error while trying to decide which value-tables to join & query", ex);
                    throw;
                }
            }

            // U5-789
            // Workaround pending a better check of what data is actually saved
            // An issue arose because previous data had been saved in long-string,
            // but the datatype changed to be just string, therefore only string was
            // being queried despite all the data residing still in long-string
            if (_typesToQuery.Contains(DataSerializationTypes.String) && !_typesToQuery.Contains(DataSerializationTypes.LongString))
            {
                _typesToQuery.Add(DataSerializationTypes.LongString);
            }

            //NodeVersion aliasNodeVersion = null;
            //Attribute aliasAttribute = null;
            //AttributeDefinition aliasAttributeDefinition = null;
            //AttributeStringValue aliasStringValue = null;
            //AttributeLongStringValue aliasLongStringValue = null;
            //AttributeIntegerValue aliasIntegerValue = null;
            //AttributeDecimalValue aliasDecimalValue = null;
            //NodeRelation aliasNodeRelation = null;
            //AttributeDateValue aliasDateValue = null;

            //QueryOver<NodeVersion, AttributeDefinition> queryExtender = QueryOver.Of<NodeVersion>(() => aliasNodeVersion)
            //    .JoinQueryOver<Attribute>(() => aliasNodeVersion.Attributes, () => aliasAttribute)
            //    .JoinQueryOver<AttributeDefinition>(() => aliasAttribute.AttributeDefinition, () => aliasAttributeDefinition);

            int numberOfMatchesEvaluated         = 0;
            AbstractCriterion restrictionBuilder = null;

            foreach (var dataSerializationTypese in _typesToQuery.Distinct())
            {
                AbstractCriterion restriction = null;
                global::System.Linq.Expressions.Expression <Func <object> > propertyExpression = null;
                global::System.Linq.Expressions.Expression <Func <object> > subkeyExpression   = null;
                List <ValuePredicateType> validClauseTypes = null;
                var useLikeMatchForStrings = false;
                switch (dataSerializationTypese)
                {
                case DataSerializationTypes.SmallInt:
                case DataSerializationTypes.LargeInt:
                case DataSerializationTypes.Boolean:
                    propertyExpression = () => integerVal.Value;
                    subkeyExpression   = () => integerVal.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.GreaterThan,
                        ValuePredicateType.GreaterThanOrEqual,
                        ValuePredicateType.LessThan,
                        ValuePredicateType.LessThanOrEqual,
                        ValuePredicateType.NotEqual
                    };
                    break;

                case DataSerializationTypes.Decimal:
                    propertyExpression = () => decimalVal.Value;
                    subkeyExpression   = () => decimalVal.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.GreaterThan,
                        ValuePredicateType.GreaterThanOrEqual,
                        ValuePredicateType.LessThan,
                        ValuePredicateType.LessThanOrEqual,
                        ValuePredicateType.NotEqual
                    };
                    break;

                case DataSerializationTypes.String:
                    propertyExpression = () => stringVal.Value;
                    subkeyExpression   = () => stringVal.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.NotEqual,
                        ValuePredicateType.Contains,
                        ValuePredicateType.StartsWith,
                        ValuePredicateType.EndsWith,
                        ValuePredicateType.MatchesWildcard
                    };
                    break;

                case DataSerializationTypes.LongString:
                    propertyExpression     = () => longStrVal.Value;
                    subkeyExpression       = () => longStrVal.ValueKey;
                    useLikeMatchForStrings = true;
                    validClauseTypes       = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.NotEqual,
                        ValuePredicateType.Contains,
                        ValuePredicateType.StartsWith,
                        ValuePredicateType.EndsWith,
                        ValuePredicateType.MatchesWildcard
                    };
                    break;

                case DataSerializationTypes.Date:
                    propertyExpression = () => dateVal.Value;
                    subkeyExpression   = () => dateVal.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.GreaterThan,
                        ValuePredicateType.GreaterThanOrEqual,
                        ValuePredicateType.LessThan,
                        ValuePredicateType.LessThanOrEqual,
                        ValuePredicateType.NotEqual,
                        ValuePredicateType.Empty
                    };
                    break;
                }

                if (!validClauseTypes.Contains(node.ValueExpression.ClauseType))
                {
                    throw new InvalidOperationException("A field of type {0} cannot be queried with operator {1}".InvariantFormat(dataSerializationTypese.ToString(), node.ValueExpression.ClauseType.ToString()));
                }

                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    restriction = GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression, subkeyExpression, valueKey);
                    break;

                case ValuePredicateType.NotEqual:
                    restriction = !GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression);
                    break;

                case ValuePredicateType.LessThan:
                    restriction = GetRestrictionLt(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.LessThanOrEqual:
                    restriction = GetRestrictionLtEq(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.GreaterThan:
                    restriction = GetRestrictionGt(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.GreaterThanOrEqual:
                    restriction = GetRestrictionGtEq(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.Contains:
                    restriction = GetRestrictionContains(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.StartsWith:
                    restriction = GetRestrictionStarts(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.EndsWith:
                    restriction = GetRestrictionEnds(fieldValue, propertyExpression);
                    break;
                }

                if (restriction != null)
                {
                    if (numberOfMatchesEvaluated == 0)
                    {
                        restrictionBuilder = restriction;
                        numberOfMatchesEvaluated++;
                    }
                    else
                    {
                        restrictionBuilder = Restrictions.Or(restriction, restrictionBuilder);
                    }
                }
            }

            var fieldNameRestriction = Restrictions.Eq(Projections.Property(() => def.Alias), fieldName);

            if (restrictionBuilder != null)
            {
                restrictionBuilder = Restrictions.And(restrictionBuilder, fieldNameRestriction);
            }
            else
            {
                restrictionBuilder = fieldNameRestriction;
            }

            return(restrictionBuilder);
        }
Example #18
0
        public override IQuery VisitFieldPredicate(FieldPredicateExpression node)
        {
            var fieldName  = node.SelectorExpression.FieldName;
            var valueKey   = node.SelectorExpression.ValueKey;
            var fieldValue = node.ValueExpression.Value != null?node.ValueExpression.Value.ToString() : string.Empty;

            var c = _manager.CreateSearchCriteria();

            switch (fieldName.ToLowerInvariant())
            {
            case "id":
                Guid idValue = GetIdValue(node);

                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    return(c.Must().Id(idValue.ToString("N"), FixedIndexedFields.EntityId).Compile());

                case ValuePredicateType.NotEqual:
                    //match all Id's (*) except...
                    return(c.Must().Id("*").Not().Id(idValue.ToString("N"), FixedIndexedFields.EntityId).Compile());

                default:
                    throw new InvalidOperationException(
                              "Cannot query an item by id by any other operator than == or !=");
                }
            }

            var attributeFieldName = FixedAttributeIndexFields.AttributePrefix + fieldName;

            if (!valueKey.IsNullOrWhiteSpace())
            {
                attributeFieldName += "." + valueKey;
            }

            //now, select the field value....
            switch (node.ValueExpression.ClauseType)
            {
            case ValuePredicateType.Equal:
                var query = c.Must().EntityType <TypedEntity>().Must();

                if (fieldValue != string.Empty)
                {
                    return(query.Field(attributeFieldName, fieldValue.Escape()).Compile());
                }

                return(query.Field(attributeFieldName, string.Empty).Compile());

            case ValuePredicateType.NotEqual:
                return(c.Must().EntityType <TypedEntity>()
                       .Must()
                       .Field(attributeFieldName, "*")
                       .Not()
                       .Field(attributeFieldName, fieldValue)
                       .Compile());

            case ValuePredicateType.MatchesWildcard:
            case ValuePredicateType.Contains:
                throw new NotSupportedException("Need to configure Examine to support start and end wildcards");
                return(c.Must().EntityType <TypedEntity>().Must().Field(attributeFieldName, fieldValue.MultipleCharacterWildcard()).Compile());

            case ValuePredicateType.StartsWith:
                return(c.Must().EntityType <TypedEntity>().Must().Field(attributeFieldName, fieldValue.MultipleCharacterWildcard()).Compile());

            case ValuePredicateType.EndsWith:
                throw new NotSupportedException("Need to configure Examine to support start with wildcards");
                return(c.Must().EntityType <TypedEntity>().Must().Field(attributeFieldName, fieldValue.MultipleCharacterWildcard()).Compile());

            default:
                throw new InvalidOperationException(
                          "This linq provider doesn't support a ClauseType of {0} for field {1}".InvariantFormat(
                              node.ValueExpression.ClauseType.ToString(), fieldName));
            }
        }
        public override FieldFilterResult VisitFieldPredicate(FieldPredicateExpression node)
        {
            var fieldName      = node.SelectorExpression.FieldName;
            var valueKey       = node.SelectorExpression.ValueKey;
            var fieldValue     = node.ValueExpression.Value;
            var fieldValueType = fieldValue != null?fieldValue.GetType() : typeof(string);

            var toReturn = new FieldFilterResult();

            RdbmsModel.Attribute att            = null;
            Node outerNode                      = null;
            AttributeStringValue     stringVal  = null;
            AttributeLongStringValue longStrVal = null;
            AttributeIntegerValue    integerVal = null;
            AttributeDecimalValue    decimalVal = null;
            AttributeDateValue       dateVal    = null;
            AttributeDefinition      def        = null;

            // First check for special cases, typically stuff that can be queried
            // that isn't necessarily a value in any of the Attribute*Value tables
            switch (fieldName.ToLowerInvariant())
            {
            case "utccreated":
                DateTimeOffset createdDtoValue = ParseDateTimeOffset(fieldValue);
                if (createdDtoValue == default(DateTime))
                {
                    break;
                }

                toReturn.NhCriterion = CreateRestriction(node.ValueExpression.ClauseType,
                                                         () => outerNode.DateCreated, createdDtoValue);

                if (toReturn.NhCriterion != null)
                {
                    toReturn.Joins.Add(new Join(() => agg.Node, () => outerNode, JoinType.InnerJoin));
                }

                break;

            case "utcmodified":
                DateTimeOffset modifiedDtoValue = ParseDateTimeOffset(fieldValue);
                if (modifiedDtoValue == default(DateTime))
                {
                    break;
                }

                toReturn.NhCriterion = CreateRestriction(node.ValueExpression.ClauseType,
                                                         () => agg.StatusDate, modifiedDtoValue);

                break;

            case "id":
                Guid idValue = GetIdValue(node);

                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    toReturn.NhCriterion = Restrictions.Eq(Projections.Property(() => agg.Node.Id), idValue);
                    break;

                case ValuePredicateType.NotEqual:
                    toReturn.NhCriterion = !Restrictions.Eq(Projections.Property(() => agg.Node.Id), idValue);
                    break;

                default:
                    throw new InvalidOperationException("Cannot query an item by id by any other operator than == or !=");
                }
                break;

            case "system-internal-selected-template":
                //TODO Pending property editors getting involved in query modification prior to being passed to hive provider,
                //manually check for queries against a template here
                if (valueKey == "TemplateId" && fieldValue != null)
                {
                    var tryParseResult = HiveId.TryParse(fieldValue.ToString());
                    if (!tryParseResult.Success || tryParseResult.Result.ProviderGroupRoot == null || tryParseResult.Result.ProviderId == null ||
                        (tryParseResult.Result.ProviderGroupRoot.AbsoluteUri != "storage://" && tryParseResult.Result.ProviderId != "templates"))
                    {
                        var normalisedFieldValue = "/" + fieldValue.ToString().TrimStart("/").TrimEnd(".") + ".";
                        // Need to convert the value into the serialized form that a HiveId would use
                        var newValue = new HiveId("storage", "templates", new HiveIdValue(normalisedFieldValue)).ToString(HiveIdFormatStyle.UriSafe);
                        fieldValue = newValue;
                    }
                    else
                    {
                        fieldValue = tryParseResult.Result.ToString(HiveIdFormatStyle.UriSafe);
                    }
                }
                break;
            }

            if (toReturn.NhCriterion != null)
            {
                // The special-case handling above has already set the criterion,
                // so we don't have to evaluate field values in this pass and can return
                return(toReturn);
            }

            // Establish which Attribute*Value tables to query
            // First look up the types of the main field
            AttributeDefinition defAlias  = null;
            AttributeType       typeAlias = null;
            var attributeType             = _activeSession.NhSession.QueryOver <AttributeDefinition>(() => defAlias)
                                            .JoinAlias(() => defAlias.AttributeType, () => typeAlias)
                                            .Where(() => defAlias.Alias == fieldName)
                                            .Select(Projections.Distinct(Projections.Property(() => typeAlias.PersistenceTypeProvider)))
                                            .Cacheable()
                                            .List <string>();

            foreach (var type in attributeType)
            {
                var typeName = type;

                // Ensure we don't do unneccessary calls to Activator.CreateInstance,
                // (_typesAlreadyEstablished lives for the lifetime of the visitor)
                // but still make sure we populate the toReturn.ValueTypesToQuery for this
                // visit to a field predicate
                if (TypesAlreadyDiscovered.ContainsKey(typeName))
                {
                    var dst = TypesAlreadyDiscovered[typeName];
                    if (toReturn.ValueTypesToQuery.Contains(dst))
                    {
                        continue;
                    }
                    toReturn.ValueTypesToQuery.Add(dst);
                }
                try
                {
                    var persisterType = Type.GetType(typeName, false);
                    if (persisterType != null)
                    {
                        var persisterInstance = Activator.CreateInstance(persisterType) as IAttributeSerializationDefinition;
                        if (persisterInstance != null && !toReturn.ValueTypesToQuery.Contains(persisterInstance.DataSerializationType))
                        {
                            toReturn.ValueTypesToQuery.Add(persisterInstance.DataSerializationType);
                            TypesAlreadyDiscovered.TryAdd(typeName, persisterInstance.DataSerializationType);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error <NhCriteriaVisitor>("Error while trying to decide which value-tables to join & query", ex);
                    throw;
                }
            }

            // U5-789
            // Workaround pending a better check of what data is actually saved
            // An issue arose because previous data had been saved in long-string,
            // but the datatype changed to be just string, therefore only string was
            // being queried despite all the data residing still in long-string
            if (toReturn.ValueTypesToQuery.Contains(DataSerializationTypes.String) && !toReturn.ValueTypesToQuery.Contains(DataSerializationTypes.LongString))
            {
                toReturn.ValueTypesToQuery.Add(DataSerializationTypes.LongString);
            }

            // Now go through the types that we've found, and set up the expressions for the criteria
            int numberOfMatchesEvaluated         = 0;
            AbstractCriterion restrictionBuilder = null;

            foreach (var dataSerializationTypese in toReturn.ValueTypesToQuery.Distinct())
            {
                AbstractCriterion restriction = null;
                global::System.Linq.Expressions.Expression <Func <object> > propertyExpression = null;
                global::System.Linq.Expressions.Expression <Func <object> > subkeyExpression   = null;
                List <ValuePredicateType> validClauseTypes = null;
                var useLikeMatchForStrings = false;
                switch (dataSerializationTypese)
                {
                case DataSerializationTypes.SmallInt:
                case DataSerializationTypes.LargeInt:
                case DataSerializationTypes.Boolean:
                    propertyExpression = () => integerVal.Value;
                    subkeyExpression   = () => integerVal.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.GreaterThan,
                        ValuePredicateType.GreaterThanOrEqual,
                        ValuePredicateType.LessThan,
                        ValuePredicateType.LessThanOrEqual,
                        ValuePredicateType.NotEqual
                    };
                    break;

                case DataSerializationTypes.Decimal:
                    propertyExpression = () => decimalVal.Value;
                    subkeyExpression   = () => decimalVal.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.GreaterThan,
                        ValuePredicateType.GreaterThanOrEqual,
                        ValuePredicateType.LessThan,
                        ValuePredicateType.LessThanOrEqual,
                        ValuePredicateType.NotEqual
                    };
                    break;

                case DataSerializationTypes.String:
                    propertyExpression = () => stringVal.Value;
                    subkeyExpression   = () => stringVal.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.NotEqual,
                        ValuePredicateType.Contains,
                        ValuePredicateType.StartsWith,
                        ValuePredicateType.EndsWith,
                        ValuePredicateType.MatchesWildcard
                    };
                    break;

                case DataSerializationTypes.LongString:
                    propertyExpression     = () => longStrVal.Value;
                    subkeyExpression       = () => longStrVal.ValueKey;
                    useLikeMatchForStrings = true;
                    validClauseTypes       = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.NotEqual,
                        ValuePredicateType.Contains,
                        ValuePredicateType.StartsWith,
                        ValuePredicateType.EndsWith,
                        ValuePredicateType.MatchesWildcard
                    };
                    break;

                case DataSerializationTypes.Date:
                    propertyExpression = () => dateVal.Value;
                    subkeyExpression   = () => dateVal.ValueKey;
                    validClauseTypes   = new List <ValuePredicateType>()
                    {
                        ValuePredicateType.Equal,
                        ValuePredicateType.GreaterThan,
                        ValuePredicateType.GreaterThanOrEqual,
                        ValuePredicateType.LessThan,
                        ValuePredicateType.LessThanOrEqual,
                        ValuePredicateType.NotEqual,
                        ValuePredicateType.Empty
                    };
                    break;
                }

                if (!validClauseTypes.Contains(node.ValueExpression.ClauseType))
                {
                    throw new InvalidOperationException("A field of type {0} cannot be queried with operator {1}".InvariantFormat(dataSerializationTypese.ToString(), node.ValueExpression.ClauseType.ToString()));
                }

                // Based on the clause type, generate an NH criterion
                switch (node.ValueExpression.ClauseType)
                {
                case ValuePredicateType.Equal:
                    restriction = GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression, subkeyExpression, valueKey);
                    break;

                case ValuePredicateType.NotEqual:
                    restriction = !GetRestrictionEq(fieldValue, useLikeMatchForStrings, propertyExpression);
                    break;

                case ValuePredicateType.LessThan:
                    restriction = GetRestrictionLt(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.LessThanOrEqual:
                    restriction = GetRestrictionLtEq(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.GreaterThan:
                    restriction = GetRestrictionGt(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.GreaterThanOrEqual:
                    restriction = GetRestrictionGtEq(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.Contains:
                    restriction = GetRestrictionContains(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.StartsWith:
                    restriction = GetRestrictionStarts(fieldValue, propertyExpression);
                    break;

                case ValuePredicateType.EndsWith:
                    restriction = GetRestrictionEnds(fieldValue, propertyExpression);
                    break;
                }

                // We might be dealing with multiple restrictions even for one field (e.g. if it's been stored once in String table, and another time in LongString)
                if (restriction != null)
                {
                    if (numberOfMatchesEvaluated == 0)
                    {
                        restrictionBuilder = restriction;
                        numberOfMatchesEvaluated++;
                    }
                    else
                    {
                        // If we're doing a second or later evaluation, turn the restriction into an Or to combine them all
                        restrictionBuilder = Restrictions.Or(restriction, restrictionBuilder);
                    }
                }
            }

            // Add the field name restriction
            var fieldNameRestriction = Restrictions.Eq(Projections.Property(() => def.Alias), fieldName);

            if (restrictionBuilder != null)
            {
                restrictionBuilder = Restrictions.And(restrictionBuilder, fieldNameRestriction);
            }
            else
            {
                restrictionBuilder = fieldNameRestriction;
            }

            // Build the query which will use the restrictions we've just generated
            var query = QueryOver.Of(() => agg);

            // Set up the basic joins (not that we're adding these to a Joins collection on our own type, not just doing
            // them on an NH query, so that we can optimise or merge the joins once the entire expression tree is evaluated
            // for example inside VisitBinary)
            toReturn.Joins.Add(new Join(() => agg.NodeVersion, () => version, JoinType.InnerJoin));
            toReturn.Joins.Add(new Join(() => version.Attributes, () => att, JoinType.InnerJoin));
            toReturn.Joins.Add(new Join(() => att.AttributeDefinition, () => def, JoinType.InnerJoin));

            // Set up the joins for the value tables - only add joins for the tables that we know we want to actually query based on
            // what VisitField might have encountered and added to toReturn.ValueTypesToQuery
            foreach (var dataSerializationTypese in toReturn.ValueTypesToQuery.Distinct())
            {
                Expression <Func <object> > path  = null;
                Expression <Func <object> > alias = null;
                switch (dataSerializationTypese)
                {
                case DataSerializationTypes.SmallInt:
                case DataSerializationTypes.LargeInt:
                case DataSerializationTypes.Boolean:
                    path  = () => att.AttributeIntegerValues;
                    alias = () => integerVal;
                    break;

                case DataSerializationTypes.Decimal:
                    path  = () => att.AttributeDecimalValues;
                    alias = () => decimalVal;
                    break;

                case DataSerializationTypes.String:
                    path  = () => att.AttributeStringValues;
                    alias = () => stringVal;
                    break;

                case DataSerializationTypes.LongString:
                    path  = () => att.AttributeLongStringValues;
                    alias = () => longStrVal;
                    break;

                case DataSerializationTypes.Date:
                    path  = () => att.AttributeDateValues;
                    alias = () => dateVal;
                    break;
                }
                toReturn.Joins.Add(new Join(path, alias));
            }

            toReturn.Subquery = query
                                .Where(restrictionBuilder)
                                .Select(x => x.NodeVersion.Id);

            toReturn.NhCriterion = restrictionBuilder;
            return(toReturn);
        }
 public override Expression VisitFieldPredicate(FieldPredicateExpression node)
 {
     StringBuilder.AppendFormat("\n{0}", node);
     return(node);
 }