def test_intersection(self):
     self.assertJson(query.intersection(), '{"intersection":[]}')
     self.assertJson(query.intersection(query.index("widget")),
                     '{"intersection":{"index":"widget"}}')
     self.assertJson(
         query.intersection(query.index("widget"), query.index("things")),
         '{"intersection":[{"index":"widget"},{"index":"things"}]}')
Ejemplo n.º 2
0
def build_document_set_intersection(
        table: sql.Table,
        filter_group: typing.Optional[sql.FilterGroup]) -> QueryExpression:
    """Build FQL match query based on intersection of filtered results from given group.

    Params:
    -------
    table: A Table object associated with a Fauna collection.
    filter_group: A group of filters representing an intersection of filtered results.

    Returns:
    --------
    FQL query expression that matches on the same conditions as the Table's filters.
    """
    filter_group_filters = [] if filter_group is None else filter_group.filters
    group_filter_names = [
        sql_filter.name for sql_filter in filter_group_filters
    ]
    filters = [
        sql_filter for sql_filter in table.filters
        if sql_filter.name in group_filter_names
    ]

    if not any(filters):
        return q.intersection(q.match(q.index(index_name(table.name))))

    document_sets = [
        _define_match_set(query_filter) for query_filter in filters
    ]
    return q.intersection(*document_sets)
Ejemplo n.º 3
0
def _fetch_column_info_refs(table_name: str, column_name: str):
    convert_to_collection_ref_set = functools.partial(
        fql.convert_to_ref_set, "information_schema_columns_")

    return q.intersection(
        convert_to_collection_ref_set(
            q.range(
                q.match(
                    q.index(
                        fql.index_name(
                            "information_schema_columns_",
                            column_name="table_name_",
                            index_type=fql.IndexType.VALUE,
                        ))),
                table_name,
                table_name,
            ), ),
        convert_to_collection_ref_set(
            q.range(
                q.match(
                    q.index(
                        fql.index_name(
                            "information_schema_columns_",
                            column_name="name_",
                            index_type=fql.IndexType.VALUE,
                        )), ),
                column_name,
                column_name,
            ), ),
    )
Ejemplo n.º 4
0
def _build_intersecting_query(
    filter_group: sql.FilterGroup,
    acc_query: typing.Optional[QueryExpression],
    table: sql.Table,
    direction: str,
) -> QueryExpression:
    opposite_direction = "left" if direction == "right" else "right"
    document_set = build_document_set_intersection(table, filter_group)

    if acc_query is None:
        intersection = document_set
    else:
        intersection = q.intersection(acc_query, document_set)

    next_table = getattr(table, f"{direction}_join_table")

    if next_table is None or table.has_columns:
        return intersection

    next_join_key = getattr(table, f"{direction}_join_key")
    assert next_join_key is not None

    if next_join_key.name == "ref":
        next_foreign_key = getattr(next_table,
                                   f"{opposite_direction}_join_key")
        assert next_foreign_key is not None

        return _build_intersecting_query(
            filter_group,
            q.join(
                intersection,
                q.index(
                    index_name(
                        next_table.name,
                        column_name=next_foreign_key.name,
                        index_type=IndexType.REF,
                    )),
            ),
            next_table,
            direction,
        )

    return _build_intersecting_query(
        filter_group,
        q.join(
            intersection,
            q.index(
                index_name(
                    table.name,
                    index_type=IndexType.REF,
                    foreign_key_name=next_join_key.name,
                )),
        ),
        next_table,
        direction,
    )
Ejemplo n.º 5
0
    def test_intersection(self):
        n_value = 102
        m_value = 202
        ref_nm = self._create(n=n_value, m=m_value)["ref"]
        self._create(n=n_value)
        self._create(m=m_value)

        q = query.intersection(query.match(self.n_index_ref, n_value),
                               query.match(self.m_index_ref, m_value))
        self.assertEqual(self._set_to_list(q), [ref_nm])
Ejemplo n.º 6
0
def join_collections(sql_query: sql.SQLQuery) -> QueryExpression:
    """Join together multiple collections to return their documents in the response.

    Params:
    -------
    sql_query: SQLQuery object with information about the query params.

    Returns:
    --------
    An FQL query expression for joined and filtered documents.
    """
    tables = sql_query.tables
    order_by = sql_query.order_by
    from_table = tables[0]
    to_table = tables[-1]
    table_with_columns = next(table for table in tables if table.has_columns)

    if (order_by is not None
            and order_by.columns[0].table_name != table_with_columns.name):
        raise exceptions.NotSupportedError(
            "Fauna uses indexes for both joining and ordering of results, "
            "and we currently can only sort the principal table "
            "(i.e. the one whose columns are being selected or modified) in the query. "
            "You can sort on a column from the principal table, query one table at a time, "
            "or remove the ordering constraint.")

    if not any(sql_query.filter_groups):
        raise exceptions.NotSupportedError(
            "Joining tables without cross-table filters via the WHERE clause is not supported. "
            "Selecting columns from multiple tables is not supported either, "
            "so there's no performance gain from joining tables without cross-table conditions "
            "for filtering query results.")

    assert from_table.left_join_table is None

    intersection_queries = []

    for filter_group in sql_query.filter_groups:
        intersection_query = q.intersection(*[
            _build_intersecting_query(filter_group, None, table, direction)
            for table, direction in [(from_table, "right"), (to_table, "left")]
        ])

        intersection_queries.append(intersection_query)

    return q.union(*intersection_queries)
Ejemplo n.º 7
0
def get_products(name=None, category=None, sort_by=None, size=5, after=None, before=None):
    sortDic = { 
        "price_asc":  q.index('products_sort_by_price_asc'),
        "price_desc": q.index('products_sort_by_price_desc'),
        "name_asc": q.index('products_sort_by_name_asc'),
        'created_at_asc': q.index('products_sort_by_created_asc')
    }

    matches = []
    if(name):
        matches.append(q.match(q.index('products_search_by_name'), name))

    if(category):
        matches.append(q.match(
            q.index('products_search_by_category'),
            q.ref(q.collection('categories'), category)
        ))

    if(len(matches) == 0):
        matches.append(q.documents(q.collection('products')))

    return fauna.query(
        q.map_(
            lambda _, ref: q.get(ref),
            q.paginate(
                q.join(
                    q.intersection(matches),
                    sortDic[sort_by or 'name_asc']
                ),
                size=size,
                after=after,
                before=before
            )
            
        )
    )