Example #1
0
def get_foreign_key_ref(
    foreign_value: QueryExpression,
    reference_collection_name: QueryExpression,
) -> QueryExpression:
    """Get the Ref to a document associated with a foreign key value.

    Params:
    -------
    foreign_value: The value to look up, usually an ID.
    references: Field metadata dict that defines the collection (key) and field name (value)
        that the foreign key refers to.

    Returns:
    --------
    Fauna query expression that returns an array of Refs for the associated document(s).
    """
    return q.let(
        {
            "is_blank_reference":
            q.or_(
                q.is_null(foreign_value),
                q.equals(foreign_value, NULL),
                q.equals(reference_collection_name, NULL),
            ),
        },
        q.if_(
            q.var("is_blank_reference"),
            None,
            q.ref(q.collection(reference_collection_name), foreign_value),
        ),
    )
Example #2
0
    def test_time_diff(self):
        qry1 = query.equals(
            1,
            query.time_diff(query.epoch(0, "second"), query.epoch(1, "second"),
                            "second"))
        qry2 = query.equals(
            0,
            query.time_diff(query.epoch(24, "hour"), query.epoch(1, "day"),
                            "day"))

        self.assertEqual(self._q(qry1), True)
        self.assertEqual(self._q(qry2), True)
Example #3
0
    def unsubscribe_from_anime(self, anime_doc_id: str):
        try:
            anime = client.query(
                q.get(q.ref(q.collection(animes), anime_doc_id)))
            client.query(
                q.let(
                    {
                        'anime_ref':
                        q.ref(q.collection(animes), anime_doc_id),
                        'bot_user':
                        q.ref(q.collection(users), self.chat_id),
                        'followers':
                        q.select(['data', 'followers'],
                                 q.get(q.var('anime_ref'))),
                    },
                    q.do(
                        q.update(
                            q.var('anime_ref'), {
                                'data': {
                                    'followers': q.subtract(
                                        q.var('followers'), 1)
                                }
                            }),
                        q.update(
                            q.var('bot_user'), {
                                'data': {
                                    'animes_watching':
                                    q.filter_(
                                        q.lambda_(
                                            'watched_anime_ref',
                                            q.not_(
                                                q.equals(
                                                    q.var('watched_anime_ref'),
                                                    q.var('anime_ref')))),
                                        q.select(['data', 'animes_watching'],
                                                 q.get(q.var('bot_user'))))
                                }
                            }),
                        q.if_(q.equals(q.var('followers'), 1),
                              q.delete(q.var('anime_ref')), 'successful!'))))

            updater.bot.send_message(chat_id=self.chat_id,
                                     text='You have stopped following ' +
                                     anime['data']['title'])
        except errors.NotFound:
            logger.info(
                'Somehow, a user {0} almost unsubscribed from an anime that did not exist'
                .format(self.chat_id))
        except Exception as err:
            log_error(err)
Example #4
0
def _load_predictions(data):
    predictions = data["predictions"]
    records = list(predictions.values())

    build_document = lambda prediction: q.to_object(
        q.map_(
            q.lambda_(
                ["key", "value"],
                [
                    q.var("key"),
                    q.if_(
                        q.equals(q.var("key"), "predicted_winner_id"),
                        _assign_ref(q.var("teams"), q.var("team_map"), q.var("value")),
                        q.if_(
                            q.equals(q.var("key"), "match_id"),
                            _assign_ref(
                                q.var("matches"), q.var("match_map"), q.var("value")
                            ),
                            q.if_(
                                q.equals(q.var("key"), "ml_model_id"),
                                _assign_ref(
                                    q.var("ml_models"),
                                    q.var("ml_model_map"),
                                    q.var("value"),
                                ),
                                q.var("value"),
                            ),
                        ),
                    ),
                ],
            ),
            q.to_array(prediction),
        )
    )
    let_params = {
        "collection": q.collection("predictions"),
        "teams": q.collection("teams"),
        "team_map": data["teams"],
        "matches": q.collection("matches"),
        "match_map": data["matches"],
        "ml_models": q.collection("ml_models"),
        "ml_model_map": data["ml_models"],
    }

    documents = _create_documents(let_params, records, build_document)

    for record, document in zip(records, documents):
        record["id"] = document["ref"].id()
Example #5
0
  def test_filter(self):
    evens = query.filter_(lambda a: query.equals(query.modulo(a, 2), 0), [1, 2, 3, 4])
    self.assertEqual(self._q(evens), [2, 4])

    # Works on page too
    ref = self._create(n=11, m=12)["ref"]
    self._create(n=11)
    self._create(n=11)

    page = query.paginate(query.match(self.n_index_ref, 11))
    refs_with_m = query.filter_(lambda a: query.contains_path(["data", "m"], query.get(a)), page)
    self.assertEqual(self._q(refs_with_m), {"data": [ref]})
 def test_equals(self):
     self.assertJson(query.equals(1), '{"equals":1}')
     self.assertJson(query.equals(1, 2), '{"equals":[1,2]}')
     self.assertJson(query.equals([1, 2]), '{"equals":[1,2]}')
Example #7
0
 def test_equals(self):
     self.assertTrue(self._q(query.equals(1, 1, 1)))
     self.assertFalse(self._q(query.equals(1, 1, 2)))
     self.assertTrue(self._q(query.equals(1)))
     self._assert_bad_query(query.equals())
Example #8
0
    def test_now(self):
        t1 = self._q(query.now())
        self.assertIsInstance(t1, FaunaTime)

        self.assertEqual(self._q(query.equals(query.now(), query.time("now"))),
                         True)
Example #9
0
def create_roles(client):
    roles = [{
        "name":
        "admin",
        "membership": [{
            "resource":
            q.collection("users"),
            "predicate":
            q.query(lambda ref: q.equals(
                q.select(["data", "type"], q.get(ref)), "admin"))
        }],
        "privileges": [{
            "resource": q.collection("categories"),
            "actions": {
                "read": True,
                "create": True,
                "write": True
            }
        }, {
            "resource": q.collection("products"),
            "actions": {
                "read": True,
                "write": True,
                "create": True
            }
        }, {
            "resource": q.collection("users"),
            "actions": {
                "read": True,
                "create": True,
                "write": True
            }
        }, {
            "resource": q.collection("orders"),
            "actions": {
                "read": True,
                "write": True,
                "create": True
            }
        }, {
            "resource":
            objects.Ref("check_if_categories_exists",
                        objects.Ref("functions")),
            "actions": {
                "call": True
            }
        }]
    }, {
        "name":
        "customer",
        "membership": [{
            "resource":
            q.collection("users"),
            "predicate":
            q.query(lambda ref: q.equals(
                q.select(["data", "type"], q.get(ref)), "customer"))
        }],
        "privileges": [{
            "resource":
            objects.Ref("purchase", objects.Ref("functions")),
            "actions": {
                "call": True
            }
        }, {
            "resource":
            objects.Ref("get_order_status_history", objects.Ref("functions")),
            "actions": {
                "call":
                q.query(lambda ref: q.equals(
                    q.current_identity(),
                    q.select(["data", "customer"], q.get(ref)))),
            }
        }, {
            "resource": q.collection("users"),
            "actions": {
                "read":
                q.query(lambda ref: q.equals(q.current_identity(), ref)),
                "write":
                q.query(lambda ref: q.equals(q.current_identity(), ref)),
            }
        }, {
            "resource": q.collection("orders"),
            "actions": {
                "read":
                q.query(lambda ref: q.equals(
                    q.current_identity(),
                    q.select(["data", "customer"], q.get(ref)))),
            }
        }]
    }]
    client.query(q.map_(lambda role: q.create_role(role), roles))
Example #10
0
def translate_select(sql_query: sql.SQLQuery) -> QueryExpression:
    """Translate a SELECT SQL query into an equivalent FQL query.

    Params:
    -------
    sql_query: An SQLQuery instance.

    Returns:
    --------
    An FQL query expression based on the SQL query.
    """
    document_pages = _define_document_pages(sql_query)
    selected_table = next(table for table in sql_query.tables
                          if table.has_columns)

    get_field_value = lambda function_value, raw_value: q.if_(
        q.equals(function_value, common.NULL),
        q.if_(q.equals(raw_value, common.NULL), None, raw_value),
        q.select([common.DATA, 0], function_value),
    )

    calculate_function_value = lambda document_set, function_name: q.if_(
        q.is_null(function_name),
        common.NULL,
        q.if_(
            q.equals(function_name, sql.Function.COUNT.value),
            q.count(document_set),
            common.NULL,
        ),
    )

    # With aggregation functions, standard behaviour is to include the first value
    # if any column selections are part of the query, at least until we add support
    # for GROUP BY
    get_first_document = lambda documents: q.if_(q.is_empty(documents), [{}],
                                                 q.take(1, documents))

    translate_document_fields = lambda maybe_documents: q.let(
        {
            # We map over selected_fields to build document object
            # to maintain the order of fields as queried. Otherwise,
            # SQLAlchemy gets confused and assigns values to the incorrect keys.
            "selected_column_info":
            [[col.table_name, col.name, col.function_name]
             for col in sql_query.columns],
            "has_functions":
            any(col.function_name for col in sql_query.columns),
            "maybe_document_set":
            q.if_(
                q.var("has_functions"),
                get_first_document(maybe_documents),
                maybe_documents,
            ),
            "field_alias_map":
            sql_query.alias_map,
        },
        q.map_(
            q.lambda_(
                "maybe_document",
                q.let(
                    {
                        "document":
                        q.if_(
                            q.is_ref(q.var("maybe_document")),
                            {
                                # We use the selected table name here instead of deriving
                                # the collection name from the document ref in order to
                                # save a 'get' call from inside of a map, which could get
                                # expensive.
                                selected_table.name:
                                q.merge(
                                    q.select(
                                        common.DATA,
                                        q.get(q.var("maybe_document")),
                                    ),
                                    {"ref": q.var("maybe_document")},
                                ),
                            },
                            q.var("maybe_document"),
                        ),
                    },
                    q.to_object(
                        q.map_(
                            q.lambda_(
                                [
                                    "collection_name", "field_name",
                                    "function_name"
                                ],
                                q.let(
                                    {
                                        "function_value":
                                        calculate_function_value(
                                            maybe_documents,
                                            q.var("function_name")),
                                        "raw_value":
                                        q.select(
                                            [
                                                q.var("collection_name"),
                                                q.var("field_name"),
                                            ],
                                            q.var("document"),
                                            default=common.NULL,
                                        ),
                                    },
                                    [
                                        q.select(
                                            [
                                                q.var("collection_name"),
                                                q.var("field_name"),
                                            ],
                                            q.var("field_alias_map"),
                                        ),
                                        get_field_value(
                                            q.var("function_value"),
                                            q.var("raw_value")),
                                    ],
                                ),
                            ),
                            q.var("selected_column_info"),
                        )),
                ),
            ),
            q.var("maybe_document_set"),
        ),
    )

    return q.let(
        {
            "maybe_documents":
            document_pages,
            "translated_documents":
            translate_document_fields(q.var("maybe_documents")),
            "result":
            q.distinct(q.var("translated_documents"))
            if sql_query.distinct else q.var("translated_documents"),
        },
        # Paginated sets hold an array of results in a 'data' field, so we try to flatten it
        # in case we're dealing with pages instead of an array of results which doesn't
        # have such nesting
        {common.DATA: q.select(common.DATA, q.var("result"), q.var("result"))},
    )