Пример #1
0
 public static ReqlAst ToReqlAst(object val, Func<object, ReqlAst> hook)
 {
     return ToReqlAst(val, 100, hook);
 }
Пример #2
0
        private static ReqlAst ToReqlAst(object val, int remainingDepth, Func<object, ReqlAst> hook = null )
        {
            if( remainingDepth <= 0 )
            {
                throw new ReqlDriverCompileError("Recursion limit reached converting to ReqlAst");
            }
            if( hook != null )
            {
                var converted = hook(val);
                if( !ReferenceEquals(converted, null) )
                {
                    return converted;
                }
            }
            var ast = val as ReqlAst;
            if( !ReferenceEquals(ast, null) )
            {
                return ast;
            }

            var token = val as JToken;
            if( token != null )
            {
                return new Poco(token);
            }

            var lst = val as IList;
            if( lst != null )
            {
                Arguments innerValues = new Arguments();
                foreach( object innerValue in lst )
                {
                    innerValues.Add(ToReqlAst(innerValue, remainingDepth - 1));
                }
                return new MakeArray(innerValues, null);
            }

            var dict = val as IDictionary;
            if( dict != null )
            {
                var obj = new Dictionary<string, ReqlAst>();
                foreach( var keyObj in dict.Keys )
                {
                    var key = keyObj as string;
                    if( key == null )
                    {
                        throw new ReqlDriverCompileError("Object keys can only be strings");
                    }

                    obj[key] = ToReqlAst(dict[keyObj]);
                }
                return MakeObj.fromMap(obj);
            }

            var del = val as Delegate;
            if( del != null )
            {
                return Func.FromLambda(del);
            }

            var dt = val as DateTime?;
            if (dt != null)
            {
                return new Poco(dt);
            }
            var dto = val as DateTimeOffset?;
            if (dto != null)
            {
                return new Poco(dto);
            }

            var @int = val as int?;
            if( @int != null )
            {
                return new Datum(@int);
            }

            if( IsNumber(val) )
            {
                return new Datum(val);
            }

            var @bool = val as bool?;
            if( @bool != null )
            {
                return new Datum(@bool);
            }

            var str = val as string;
            if( str != null )
            {
                return new Datum(str);
            }
            if( val == null )
            {
                return new Datum(null);
            }

            return new Poco(val);
        }
Пример #3
0
        public async Task<ReqlExpr> AsCountTableQueryAsync(RethinkDB rdb, Table table, string requesterId, string feedOwnerId, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Make sure we have all the data we need.
            await this.resolveDependenciesRunner.RunOnce(cancellationToken);

            // Find the name of the index to use.
            var index = this.TableIndex();

            // Find the date boundary values.
            var lowerDateBound = this.boundaries?.TryGetValue(TentFeedRequestBoundaryType.Since)?.Date
                ?? this.boundaries?.TryGetValue(TentFeedRequestBoundaryType.Until)?.Date;
            var upperDateBound = this.boundaries?.TryGetValue(TentFeedRequestBoundaryType.Before)?.Date;

            // Filter by owner and date.
            var query = (ReqlExpr)table.Between(
                new object[] { feedOwnerId, lowerDateBound != null ? rdb.Expr(lowerDateBound) : rdb.Minval() },
                new object[] { feedOwnerId, upperDateBound != null ? rdb.Expr(upperDateBound) : rdb.Maxval() })[new
                {
                    index,
                    left_bound = "open",
                    right_bound = "open"
                }];

            // Set the order-by depending on the boundary type.
            query = query.OrderBy()[new { index = this.boundaries != null && this.boundaries.ContainsKey(TentFeedRequestBoundaryType.Since) ? (object)rdb.Asc(index) : (object)rdb.Desc(index) }];

            var filters = new List<Func<ReqlExpr, ReqlExpr>>();

            // Entities.
            if (this.specialEntities == TentFeedRequestSpecialEntities.Followings)
                filters.Add(r => r.G("is_from_following").Eq(true));
            else if (this.users != null && this.users.Any())
                filters.Add(r => rdb.BetterOr(this.users.Select(u => r.G("user").Eq(u.Id)).Cast<object>().ToArray()));

            // Post type filter.
            if (this.types != null && this.types.Any())
            {
                // Condition on a single type.
                var typeCondition = new Func<ReqlExpr, ITentPostType, ReqlExpr>((r, type) => type.WildCard
                    ? (ReqlExpr)r.G("type").Match($"^{Regex.Escape(type.Type)}#")
                    : r.G("type").Eq(type.ToString()));

                // Combine the type conditions as part of an OR expression.
                filters.Add(r => rdb.BetterOr(this.types.Select(type => typeCondition(r, type)).Cast<object>().ToArray()));
            }

            // Condition on a single mention.
            var mentionCondition = new Func<ReqlExpr, ITentRequestPost, ReqlExpr>((r, mention) => r.G("mentions")
                // Map each mention for the current row to a boolean.
                .Map(m => mention.Post == null
                    ? m.G("user").Eq(mention.User.Id)
                    : rdb.BetterAnd(m.G("user").Eq(mention.User.Id), m.G("post").Eq(mention.Post.Id)))
                // Reduce the resulting booleans to just one (any).
                .Reduce((b1, b2) => rdb.BetterOr(b1, b2))
                .Default_(false));

            // Mentions.
            if (this.mentions != null && this.mentions.Any())
            {
                // Combine the mention conditions, first by AND, then by OR.
                filters.Add(r => rdb.BetterAnd(this.mentions
                    .Select(andMentions =>
                        rdb.BetterOr(andMentions.Select(mention =>
                            mentionCondition(r, mention)).Cast<object>().ToArray()))
                    .Cast<object>().ToArray()));
            }

            // Not mentions.
            if (this.notMentions != null && this.notMentions.Any())
            {
                // Combine the not mention conditions, first by AND, then by OR.
                filters.Add(r => rdb.BetterAnd(this.notMentions
                    .Select(andNotMentions =>
                        rdb.BetterOr(andNotMentions.Select(notMention =>
                            mentionCondition(r, notMention).Not()).Cast<object>().ToArray()))
                    .Cast<object>().ToArray()));
            }

            // Permissions.
            if (requesterId != feedOwnerId)
            {
                filters.Add(r => rdb.BetterAnd(
                    r.G("user").Eq(feedOwnerId),
                    rdb.BetterOr(
                        r.G("permissions").G("public").Eq(true),
                        r.G("permissions").G("users").Contains(requesterId))));
            }

            // Apply all the filters as part of an AND expression.
            if (filters.Any())
                query = query.Filter(r => rdb.BetterAnd(filters.Select(f => f(r)).Cast<object>().ToArray()));

            return query;
        }