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), ), )
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)
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)
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()
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]}')
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())
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)
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))
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"))}, )