Beispiel #1
0
 protected virtual string CompileCondition(WhereCondition condition, SqlCompilerContext context)
 {
     return(condition switch
     {
         CompareColumnsCondition compareColumnsCondition => CompileCondition(compareColumnsCondition, context),
         CompareCondition compareCondition => CompileCondition(compareCondition, context),
         InCondition inCondition => CompileCondition(inCondition, context),
         NestedCondition nestedCondition => CompileCondition(nestedCondition, context),
         RawCondition rawCondition => CompileCondition(rawCondition, context),
         _ => throw new ArgumentOutOfRangeException(nameof(condition))
     });
Beispiel #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="node"></param>
        /// <param name="context"></param>
        /// <param name="batchScope"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public virtual SqlResult Compile(Node node, IResolveFieldContext context, IEnumerable?batchScope = null)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // TODO: Should we validate the node?

            var selections         = new List <string>();
            var tables             = new List <string>();
            var wheres             = new List <WhereCondition>();
            var orders             = new List <string>();
            var sqlCompilerContext = new SqlCompilerContext(this);

            StringifySqlAst(null, node, Array.Empty <string>(), context, selections, tables, wheres, orders, batchScope ?? Enumerable.Empty <object>(),
                            sqlCompilerContext);

            var sb = new StringBuilder();

            sb.AppendLine("SELECT");
            sb.Append("  ");
            sb.AppendLine(string.Join(",\n  ", selections));
            sb.AppendLine(string.Join("\n", tables));

            if (wheres.Count > 0)
            {
                sb.Append("WHERE ");
                sb.AppendLine(_dialect.CompileConditions(wheres, sqlCompilerContext));
            }

            if (orders.Count > 0)
            {
                sb.Append("ORDER BY ");
                sb.AppendLine(string.Join(", ", orders));
            }

            return(new SqlResult(sb.ToString().Trim(), sqlCompilerContext.Parameters));
        }
Beispiel #3
0
 public override void HandleBatchedManyToManyPaginated(Node?parent, SqlTable node, IReadOnlyDictionary <string, object> arguments,
                                                       IResolveFieldContext context, ICollection <string> tables, IEnumerable <object> batchScope, SqlCompilerContext compilerContext,
                                                       string joinCondition) => throw new NotSupportedException();
Beispiel #4
0
 /// <inheritdoc />
 public override void HandlePaginationAtRoot(Node?parent, SqlTable node, IReadOnlyDictionary <string, object> arguments, IResolveFieldContext context,
                                             ICollection <string> tables, SqlCompilerContext compilerContext) => throw new NotSupportedException();
Beispiel #5
0
 /// <inheritdoc />
 public override void HandleJoinedOneToManyPaginated(SqlTable parent, SqlTable node,
                                                     IReadOnlyDictionary <string, object> arguments, IResolveFieldContext context, ICollection <string> tables,
                                                     SqlCompilerContext compilerContext, string?joinCondition) => throw new NotSupportedException();
Beispiel #6
0
        /// <inheritdoc />
        public virtual string CompileConditions(IEnumerable <WhereCondition> conditions, SqlCompilerContext context)
        {
            if (conditions == null)
            {
                throw new ArgumentNullException(nameof(conditions));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var result = new StringBuilder();

            using var enumerator = conditions.GetEnumerator();
            var i = 0;

            while (enumerator.MoveNext())
            {
                var condition = enumerator.Current;

                var compiled = CompileCondition(condition, context);

                if (string.IsNullOrEmpty(compiled))
                {
                    continue;
                }

                var boolOperator = i == 0 ? "" : condition.IsOr ? " OR " : " AND ";
                result.AppendFormat("{0}{1}", boolOperator, compiled);
                i++;
            }

            return(result.ToString());
        }
Beispiel #7
0
 /// <inheritdoc />
 public abstract void HandleBatchedManyToManyPaginated(Node?parent, SqlTable node, IReadOnlyDictionary <string, object> arguments,
                                                       IResolveFieldContext context, ICollection <string> tables, IEnumerable <object> batchScope, SqlCompilerContext compilerContext, string joinCondition);
Beispiel #8
0
 /// <inheritdoc />
 public abstract void HandlePaginationAtRoot(Node?parent, SqlTable node, IReadOnlyDictionary <string, object> arguments,
                                             IResolveFieldContext context, ICollection <string> tables, SqlCompilerContext compilerContext);
Beispiel #9
0
 /// <inheritdoc />
 public abstract void HandleJoinedOneToManyPaginated(SqlTable parent, SqlTable node,
                                                     IReadOnlyDictionary <string, object> arguments, IResolveFieldContext context, ICollection <string> tables,
                                                     SqlCompilerContext compilerContext, string?joinCondition);
Beispiel #10
0
        private void StringifySqlAst(Node?parent, Node node, IReadOnlyCollection <string> prefix,
                                     IResolveFieldContext context, ICollection <string> selections, ICollection <string> tables,
                                     ICollection <WhereCondition> wheres, ICollection <string> orders, IEnumerable batchScope,
                                     SqlCompilerContext compilerContext)
        {
            switch (node)
            {
            case SqlTable sqlTable:
                HandleTable(parent, sqlTable, prefix, context, selections, tables, wheres, orders, batchScope, compilerContext);

                if (ThisIsNotTheEndOfThisBatch(parent, sqlTable))
                {
                    foreach (var child in sqlTable.Children)
                    {
                        StringifySqlAst(node, child, new List <string>(prefix)
                        {
                            sqlTable.As
                        }, context, selections,
                                        tables, wheres, orders, batchScope, compilerContext);
                    }
                }

                break;

            case SqlColumn sqlColumn:
            {
                if (!(parent is SqlTable table))
                {
                    throw new ArgumentException($"'{nameof(parent)}' must be of type {typeof(SqlTable)}",
                                                nameof(parent));
                }

                var    parentTable = table.As;
                string columnName;

                if (sqlColumn.Expression != null)
                {
                    columnName = sqlColumn.Expression(_dialect.Quote(parentTable), sqlColumn.Arguments, context, table);
                }
                else if (table.ColumnExpression != null)
                {
                    columnName = table.ColumnExpression(_dialect.Quote(parentTable), sqlColumn.Name, sqlColumn.Arguments, context);
                }
                else
                {
                    columnName = $"{_dialect.Quote(parentTable)}.{_dialect.Quote(sqlColumn.Name)}";
                }

                selections.Add($"{columnName} AS {_dialect.Quote(JoinPrefix(prefix) + sqlColumn.As)}");
                break;
            }

            case SqlComposite sqlComposite:
            {
                if (!(parent is SqlTable table))
                {
                    throw new ArgumentException($"'{nameof(parent)}' must be of type {typeof(SqlTable)}", nameof(parent));
                }

                var parentTable = table.As;
                selections.Add($"{_dialect.CompositeKey(parentTable, sqlComposite.Name)} AS {_dialect.Quote(JoinPrefix(prefix) + sqlComposite.As)}");
                break;
            }

            case SqlJunction _:
            case SqlNoop _:
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(node), $"Don't know how to handle {node.GetType()}.");
            }
        }
Beispiel #11
0
        private void HandleTable(Node?parent, SqlTable node, IEnumerable <string> prefix,
                                 IResolveFieldContext context, ICollection <string> selections, ICollection <string> tables,
                                 ICollection <WhereCondition> wheres, ICollection <string> orders, IEnumerable batchScope,
                                 SqlCompilerContext compilerContext)
        {
            var arguments = node.Arguments;

            // also check for batching
            if (node.Paginate == false && (node.Batch == null || node.Junction?.Batch == null || parent == null))
            {
                if (node.Junction?.Where != null)
                {
                    var whereBuilder = new WhereBuilder(_dialect.Quote(node.Junction.As), wheres);
                    node.Junction.Where.Invoke(whereBuilder, arguments, context, node);
                }

                // only add the where clause if there's no join or the join is not paginated
                if (node.Where != null)
                {
                    var whereBuilder = new WhereBuilder(_dialect.Quote(node.As), wheres);
                    node.Where.Invoke(whereBuilder, arguments, context, node);
                }
            }

            if (ThisIsNotTheEndOfThisBatch(parent, node))
            {
                if (node.Junction?.OrderBy != null)
                {
                    var junctionOrderBy = _dialect.CompileOrderBy(node.Junction.OrderBy);
                    orders.Add(junctionOrderBy);
                }

                if (node.OrderBy != null)
                {
                    var orderBy = _dialect.CompileOrderBy(node.OrderBy);
                    orders.Add(orderBy);
                }

                // if (node.Junction?.SortKey != null)
                // {
                //     var junctionOrderBy =  _dialect.CompileOrderBy(node.Junction.SortKey);
                //     orders.Add(junctionOrderBy);
                // }
                //
                // if (node.SortKey != null)
                // {
                //     var orderBy = _dialect.CompileOrderBy(node.SortKey);
                //     orders.Add(orderBy);
                // }
            }

            if (node.Join != null)
            {
                if (parent is SqlTable parentTable)
                {
                    var join = new JoinBuilder(_dialect.Quote(parentTable.Name), _dialect.Quote(parentTable.As),
                                               _dialect.Quote(node.Name), _dialect.Quote(node.As));
                    node.Join(join, arguments, context, node);

                    if (node.Paginate)
                    {
                        _dialect.HandleJoinedOneToManyPaginated(parentTable, node, arguments, context, tables, compilerContext,
                                                                join.Condition == null ? null : _dialect.CompileConditions(new[] { join.Condition }, compilerContext));
                    }
                    else if (join.Condition is RawCondition)
                    {
                        tables.Add($"{join.From} ON {_dialect.CompileConditions(new[] {join.Condition}, compilerContext)}");
                    }
                    else if (join.Condition != null)
                    {
                        tables.Add($"LEFT JOIN {_dialect.Quote(node.Name)} {_dialect.Quote(node.As)} ON {_dialect.CompileConditions(new[] {join.Condition}, compilerContext)}");
                    }

                    return;
                }
            }
            else if (node.Junction?.Batch != null)
            {
                if (parent is SqlTable parentTable)
                {
                    string columnName;

                    if (node.Junction.Batch.ParentKey.Expression != null)
                    {
                        columnName = node.Junction.Batch.ParentKey.Expression(_dialect.Quote(parentTable.As), node.Junction.Batch.ParentKey.Arguments, context, node);
                    }
                    else
                    {
                        columnName = $"{_dialect.Quote(parentTable.As)}.{_dialect.Quote(node.Junction.Batch.ParentKey.Name)}";
                    }

                    selections.Add($"{columnName} AS ${_dialect.Quote(JoinPrefix(prefix) + node.Junction.Batch.ParentKey.As)}");
                }
                else
                {
                    var join = new JoinBuilder(_dialect.Quote(node.Name), _dialect.Quote(node.As), _dialect.Quote(node.Junction.Table), _dialect.Quote(node.Junction.As));

                    if (node.Junction.Batch.Join != null)
                    {
                        node.Junction.Batch.Join(join, arguments, context, node);
                    }

                    if (join.Condition == null)
                    {
                        throw new JoinMonsterException($"The 'batch' join condition on table '{node.Name}' for junction '{node.Junction.Table}' cannot be null.");
                    }


                    var joinCondition = _dialect.CompileConditions(new[] { join.Condition }, compilerContext);

                    if (node.Paginate)
                    {
                        _dialect.HandleBatchedManyToManyPaginated(parent, node, arguments, context, tables, batchScope.Cast <object>(),
                                                                  compilerContext, joinCondition);
                    }
                    else
                    {
                        tables.Add($"FROM {_dialect.Quote(node.Junction.Table)} {_dialect.Quote(node.Junction.As)}");
                        tables.Add($"LEFT JOIN {_dialect.Quote(node.Name)} {_dialect.Quote(node.As)} ON {joinCondition}");

                        var column       = _dialect.Quote(node.Junction.Batch.ThisKey.Name);
                        var whereBuilder = new WhereBuilder(_dialect.Quote(node.Junction.As), wheres);
                        if (node.Junction.Batch.Where != null)
                        {
                            node.Junction.Batch.Where(whereBuilder, column, batchScope, arguments, context, node);
                        }
                        else
                        {
                            whereBuilder.In(column, batchScope);
                        }
                    }
                }
            }
            else if (node.Junction?.FromParent != null && node.Junction?.ToChild != null)
            {
                if (parent is SqlTable parentTable)
                {
                    // TODO: Handle batching and paging
                    var fromParentJoin = new JoinBuilder(_dialect.Quote(parentTable.Name), _dialect.Quote(parentTable.As), _dialect.Quote(node.Junction.Table), _dialect.Quote(node.Junction.As));
                    var toChildJoin    = new JoinBuilder(_dialect.Quote(parentTable.Name), _dialect.Quote(node.Junction.As), _dialect.Quote(node.Name), _dialect.Quote(node.As));
                    node.Junction.FromParent(fromParentJoin, arguments, context, node);
                    node.Junction.ToChild(toChildJoin, arguments, context, node);

                    if (fromParentJoin.Condition == null)
                    {
                        throw new JoinMonsterException($"The 'fromParent' join condition on table '{node.Name}' for junction '{node.Junction.Table}' cannot be null.");
                    }
                    if (toChildJoin.Condition == null)
                    {
                        throw new JoinMonsterException($"The 'toChild' join condition on table '{node.Name}' for junction '{node.Junction.Table}' cannot be null.");
                    }

                    var compiledFromParentJoinCondition = _dialect.CompileConditions(new[] { fromParentJoin.Condition }, compilerContext);
                    var compiledToChildJoinCondition    = _dialect.CompileConditions(new[] { toChildJoin.Condition }, compilerContext);

                    if (node.Paginate)
                    {
                        // _dialect.HandleJoinedManyToManyPaginated();
                    }
                    else
                    {
                        if (fromParentJoin.Condition is RawCondition)
                        {
                            tables.Add($"{fromParentJoin.From} ON {compiledFromParentJoinCondition}");
                        }
                        else
                        {
                            tables.Add(
                                $"LEFT JOIN {_dialect.Quote(node.Junction.Table)} {_dialect.Quote(node.Junction.As)} ON {compiledFromParentJoinCondition}");
                        }

                        if (toChildJoin.Condition is RawCondition)
                        {
                            tables.Add($"{toChildJoin.From} ON {compiledToChildJoinCondition}");
                        }
                        else
                        {
                            tables.Add($"LEFT JOIN {_dialect.Quote(node.Name)} {_dialect.Quote(node.As)} ON {compiledToChildJoinCondition}");
                        }
                    }
                }

                return;
            }
            else if (node.Batch != null)
            {
                if (parent is SqlTable parentTable)
                {
                    string columnName;

                    if (node.Batch.ParentKey.Expression != null)
                    {
                        columnName = node.Batch.ParentKey.Expression(_dialect.Quote(parentTable.As), node.Batch.ParentKey.Arguments, context, node);
                    }
                    else
                    {
                        columnName = $"{_dialect.Quote(parentTable.As)}.{_dialect.Quote(node.Batch.ParentKey.Name)}";
                    }

                    selections.Add($"{columnName} AS {_dialect.Quote(JoinPrefix(prefix) + node.Batch.ParentKey.As)}");
                }
                else if (node.Paginate)
                {
                    _dialect.HandleBatchedOneToManyPaginated(parent, node, arguments, context, tables, batchScope.Cast <object>(), compilerContext);
                }
                else
                {
                    tables.Add($"FROM {_dialect.Quote(node.Name)} AS {_dialect.Quote(node.As)}");

                    var column       = _dialect.Quote(node.Batch.ThisKey.Name);
                    var whereBuilder = new WhereBuilder(_dialect.Quote(node.As), wheres);
                    if (node.Batch.Where != null)
                    {
                        node.Batch.Where(whereBuilder, column, batchScope, arguments, context, node);
                    }
                    else
                    {
                        whereBuilder.In(column, batchScope);
                    }
                }

                return;
            }
            else if (node.Paginate)
            {
                _dialect.HandlePaginationAtRoot(parent, node, arguments, context, tables, compilerContext);
                return;
            }

            tables.Add($"FROM {_dialect.Quote(node.Name)} AS {_dialect.Quote(node.As)}");
        }
Beispiel #12
0
        /// <inheritdoc />
        public override void HandleJoinedOneToManyPaginated(SqlTable parent, SqlTable node,
                                                            IReadOnlyDictionary <string, object> arguments, IResolveFieldContext context, ICollection <string> tables,
                                                            SqlCompilerContext compilerContext, string?joinCondition)
        {
            if (parent == null)
            {
                throw new ArgumentNullException(nameof(parent));
            }
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (arguments == null)
            {
                throw new ArgumentNullException(nameof(arguments));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (tables == null)
            {
                throw new ArgumentNullException(nameof(tables));
            }

            if (node.Join == null)
            {
                throw new JoinMonsterException($"{nameof(node)}.{nameof(node.Join)} on table '{node.Name}' cannot be null.");
            }

            var join = new JoinBuilder(Quote(parent.Name), Quote(parent.As), Quote(node.Name), Quote(node.As));

            node.Join(join, arguments, context, node);

            if (join.Condition == null)
            {
                throw new JoinMonsterException($"The join condition on table '{node.Name}' cannot be null.");
            }

            var pagingWhereConditions = new List <WhereCondition>
            {
                join.Condition
            };

            if (node.Where != null)
            {
                var whereBuilder = new WhereBuilder(Quote(node.As), pagingWhereConditions);
                node.Where.Invoke(whereBuilder, arguments, context, node);
            }

            if (node.SortKey != null)
            {
                var(limit, order, whereCondition) = InterpretForKeysetPaging(node, arguments, context);
                if (whereCondition != null)
                {
                    pagingWhereConditions.Add(whereCondition);
                }
                tables.Add(KeysetPagingSelect(node.Name, pagingWhereConditions, order, limit, node.As, joinCondition, "LEFT", compilerContext));
            }
            else if (node.OrderBy != null)
            {
                var(limit, offset, order) = InterpretForOffsetPaging(node, arguments, context);
                tables.Add(OffsetPagingSelect(node.Name, pagingWhereConditions, order, limit, offset,
                                              node.As, joinCondition, "LEFT", compilerContext));
            }
            else
            {
                throw new JoinMonsterException("Cannot paginate without a SortKey or an OrderBy clause.");
            }
        }
Beispiel #13
0
        public override void HandleBatchedManyToManyPaginated(Node?parent, SqlTable node, IReadOnlyDictionary <string, object> arguments,
                                                              IResolveFieldContext context, ICollection <string> tables, IEnumerable <object> batchScope, SqlCompilerContext compilerContext,
                                                              string joinCondition)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (arguments == null)
            {
                throw new ArgumentNullException(nameof(arguments));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (tables == null)
            {
                throw new ArgumentNullException(nameof(tables));
            }
            if (batchScope == null)
            {
                throw new ArgumentNullException(nameof(batchScope));
            }
            if (compilerContext == null)
            {
                throw new ArgumentNullException(nameof(compilerContext));
            }
            if (joinCondition == null)
            {
                throw new ArgumentNullException(nameof(joinCondition));
            }

            if (node.Junction == null)
            {
                throw new InvalidOperationException("node.Junction cannot be null.");
            }

            if (node.Junction.Batch == null)
            {
                throw new InvalidOperationException("node.Junction.Batch cannot be null.");
            }

            // var thisKeyOperand = GenerateCastExpressionFromValueType(
            //     $"${node.Junction.As}.{node.Junction.Batch.ThisKey.Name}",
            //     batchScope.ElementAtOrDefault(0)
            // );
            var thisKeyOperand = $"${node.Junction.As}.{node.Junction.Batch.ThisKey.Name}";

            var whereConditions = new List <WhereCondition>
            {
                new RawCondition($"{thisKeyOperand} = temp.\"{node.Junction.Batch.ParentKey.Name}\"", null)
            };

            if (node.Junction.Where != null)
            {
                var whereBuilder = new WhereBuilder(node.Junction.As, whereConditions);
                node.Junction.Where(whereBuilder, arguments, context, node);
            }

            if (node.Where != null)
            {
                var whereBuilder = new WhereBuilder(node.As, whereConditions);

                node.Where(whereBuilder, arguments, context, node);
            }

            var tempTable =
                $"FROM (VALUES {string.Join("", batchScope.Select(val => $"({val})"))}) temp(\"{node.Junction.Batch.ParentKey.Name}\")";

            tables.Add(tempTable);
            var lateralJoinCondition = $"{thisKeyOperand} = temp.\"{node.Junction.Batch.ParentKey.Name}\"";

            string?extraJoin = null;

            if (node.Where != null || node.OrderBy != null)
            {
                extraJoin = $"LEFT JOIN {node.Name} {Quote(node.As)} ON {joinCondition}";
            }

            if (node.SortKey != null || node.Junction.SortKey != null)
            {
                var(limit, order, whereCondition) = InterpretForKeysetPaging(node, arguments, context);
                whereConditions.Add(whereCondition);

                tables.Add(KeysetPagingSelect(node.Junction.Table, whereConditions, order, limit, node.Junction.As,
                                              lateralJoinCondition, "LEFT", compilerContext));
            }
            else if (node.OrderBy != null || node.Junction.OrderBy != null)
            {
                var(limit, offset, order) = InterpretForOffsetPaging(node, arguments, context);

                tables.Add(OffsetPagingSelect(node.Junction.Table, whereConditions, order, limit, offset,
                                              node.Junction.As, joinCondition, "LEFT", compilerContext, extraJoin));
            }

            tables.Add($"LEFT JOIN {node.Name} AS \"{node.As}\" ON {joinCondition}");
        }
Beispiel #14
0
        public override void HandleBatchedOneToManyPaginated(Node?parent, SqlTable node, IReadOnlyDictionary <string, object> arguments,
                                                             IResolveFieldContext context, ICollection <string> tables, IEnumerable <object> batchScope, SqlCompilerContext compilerContext)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (arguments == null)
            {
                throw new ArgumentNullException(nameof(arguments));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (tables == null)
            {
                throw new ArgumentNullException(nameof(tables));
            }
            if (batchScope == null)
            {
                throw new ArgumentNullException(nameof(batchScope));
            }
            if (compilerContext == null)
            {
                throw new ArgumentNullException(nameof(compilerContext));
            }

            if (node.Batch == null)
            {
                throw new InvalidOperationException("node.Batchcannot be null.");
            }

            var thisKeyOperand = $"${node.As}.{node.Batch.ThisKey.Name}";

            var whereConditions = new List <WhereCondition>
            {
                new RawCondition($"{thisKeyOperand} = temp.\"{node.Batch.ParentKey.Name}\"", null)
            };

            if (node.Where != null)
            {
                var whereBuilder = new WhereBuilder(node.As, whereConditions);

                node.Where(whereBuilder, arguments, context, node);
            }

            var tempTable =
                $"FROM (VALUES {string.Join("", batchScope.Select(val => $"({val})"))}) temp(\"{node.Batch.ParentKey.Name}\")";

            tables.Add(tempTable);

            var lateralJoinCondition = $"{thisKeyOperand} = temp.\"{node.Batch.ParentKey.Name}\"";

            if (node.SortKey != null)
            {
                var(limit, order, whereCondition) = InterpretForKeysetPaging(node, arguments, context);
                whereConditions.Add(whereCondition);

                tables.Add(KeysetPagingSelect(node.Name, whereConditions, order, limit, node.As, lateralJoinCondition,
                                              null, compilerContext));
            }
            else if (node.OrderBy != null)
            {
                var(limit, offset, order) = InterpretForOffsetPaging(node, arguments, context);

                tables.Add(OffsetPagingSelect(node.Name, whereConditions, order, limit, offset,
                                              node.As, lateralJoinCondition, null, compilerContext));
            }
        }
Beispiel #15
0
        /// <inheritdoc />
        public override void HandlePaginationAtRoot(Node?parent, SqlTable node, IReadOnlyDictionary <string, object> arguments, IResolveFieldContext context, ICollection <string> tables, SqlCompilerContext compilerContext)
        {
            var pagingWhereConditions = new List <WhereCondition>();

            if (node.SortKey != null)
            {
                var(limit, order, whereCondition) = InterpretForKeysetPaging(node, arguments, context);
                if (whereCondition != null)
                {
                    pagingWhereConditions.Add(whereCondition);
                }

                if (node.Where != null)
                {
                    var whereBuilder = new WhereBuilder(Quote(node.As), pagingWhereConditions);
                    node.Where.Invoke(whereBuilder, arguments, context, node);
                }

                tables.Add(KeysetPagingSelect(node.Name, pagingWhereConditions, order, limit, node.As, null, null, compilerContext));
            }
            else if (node.OrderBy != null)
            {
                var(limit, offset, order) = InterpretForOffsetPaging(node, arguments, context);

                if (node.Where != null)
                {
                    var whereBuilder = new WhereBuilder(Quote(node.As), pagingWhereConditions);
                    node.Where.Invoke(whereBuilder, arguments, context, node);
                }

                tables.Add(OffsetPagingSelect(node.Name, pagingWhereConditions, order, limit, offset, node.As, null,
                                              null, compilerContext));
            }
        }