示例#1
0
    def reduce_For(self, *kids):
        r"%reduce FOR Identifier IN Set \
                  UNION OptionallyAliasedExpr \
                  OptFilterClause OptSortClause OptSelectLimit"

        offset, limit = kids[8].val

        if offset is not None or limit is not None:
            subj = qlast.ForQuery(
                iterator_alias=kids[1].val,
                iterator=kids[3].val,
                result=kids[5].val.expr,
                result_alias=kids[5].val.alias,
                where=kids[6].val,
                orderby=kids[7].val,
                implicit=True,
            )

            self.val = qlast.SelectQuery(
                result=subj,
                offset=offset,
                limit=limit,
            )
        else:
            self.val = qlast.ForQuery(
                iterator_alias=kids[1].val,
                iterator=kids[3].val,
                result=kids[5].val.expr,
                result_alias=kids[5].val.alias,
                where=kids[6].val,
                orderby=kids[7].val,
            )
示例#2
0
 def reduce_For(self, *kids):
     r"%reduce FOR Identifier IN Set \
               UNION OptionallyAliasedExpr"
     self.val = qlast.ForQuery(
         iterator_alias=kids[1].val,
         iterator=kids[3].val,
         result=kids[5].val.expr,
         result_alias=kids[5].val.alias,
     )
示例#3
0
 def reduce_For(self, *kids):
     r"%reduce FOR Identifier IN Set \
               UNION OptionallyAliasedExpr \
               OptFilterClause OptSortClause OptSelectLimit"
     self.val = qlast.ForQuery(
         iterator_alias=kids[1].val,
         iterator=kids[3].val,
         result=kids[5].val.expr,
         result_alias=kids[5].val.alias,
         where=kids[6].val,
         orderby=kids[7].val,
         offset=kids[8].val[0],
         limit=kids[8].val[1],
     )
示例#4
0
def try_group_rewrite(
    node: qlast.Query,
    aliases: AliasGenerator,
) -> Optional[qlast.Query]:
    """
    Try to apply some syntactic rewrites of GROUP expressions so we
    can generate better code.

    The two key desugarings are:

    * Sink a shape into the internal group result

        SELECT (GROUP ...) <shape>
        [filter-clause] [order-clause] [other clauses]
        =>
        SELECT (
          FOR GROUP ...
          UNION <igroup-body> <shape>
          [filter-clause]
          [order-clause]
        ) [other clauses]

    * Convert a FOR over a group into just an internal group (and
      a trivial FOR)

        FOR g in (GROUP ...) UNION <body>
        =>
        FOR GROUP ...
        UNION (
            FOR g IN (<group-body>)
            UNION <body>
        )
    """

    # TODO: would Python's new pattern matching fit well here???

    # Sink shapes into the GROUP
    if (
        isinstance(node, qlast.SelectQuery)
        and isinstance(node.result, qlast.Shape)
        and isinstance(node.result.expr, qlast.GroupQuery)
    ):
        igroup = desugar_group(node.result.expr, aliases)
        igroup = igroup.replace(result=qlast.Shape(
            expr=igroup.result, elements=node.result.elements))

        # FILTER gets sunk into the body of the FOR GROUP
        if node.where or node.orderby:
            igroup = igroup.replace(
                # We need to move the result_alias in case
                # the FILTER depends on it.
                result_alias=node.result_alias,
                where=node.where,
                orderby=node.orderby,
            )

        return node.replace(
            result=igroup, result_alias=None, where=None, orderby=None)

    # Eliminate FORs over GROUPs
    if (
        isinstance(node, qlast.ForQuery)
        and isinstance(node.iterator, qlast.GroupQuery)
    ):
        igroup = desugar_group(node.iterator, aliases)
        new_result = qlast.ForQuery(
            iterator_alias=node.iterator_alias,
            iterator=igroup.result,
            result=node.result,
        )
        return igroup.replace(result=new_result, aliases=node.aliases)

    return None