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, ), ), )
def test_range(self): data = list(range(1, 20)) self._q(query.create_collection({"name": "range_test"})) self._q( query.create_index({ "name": "range_idx", "source": query.collection("range_test"), "active": True, "values": [{ "field": ["data", "value"] }] })) self._q( query.foreach( query.lambda_query(lambda x: query.create( query.collection("range_test"), {"data": { "value": x }})), data)) m = query.match(query.index("range_idx")) q1 = query.select("data", query.paginate(query.range(m, 3, 8))) q2 = query.select("data", query.paginate(query.range(m, 17, 18))) q3 = query.select("data", query.paginate(query.range(m, 19, 0))) self.assertEqual(self._q(q1), [3, 4, 5, 6, 7, 8]) self.assertEqual(self._q(q2), [17, 18]) self.assertEqual(self._q(q3), [])
def test_range(self): self.assertJson(query.range( query.match(query.ref("indexes/spellbooks_by_owner"), query.ref("collections/characters/104979509695139637")), 10, 50, ), '{"from":10,"range":{"match":{"@ref":"indexes/spellbooks_by_owner"},"terms":{"@ref":"collections/characters/104979509695139637"}},"to":50}')
def translate_drop( statement: token_groups.Statement) -> typing.List[QueryExpression]: """Translate a DROP SQL query into an equivalent FQL query. Params: ------- statement: An SQL statement returned by sqlparse. Returns: -------- An FQL query expression. """ idx, _ = statement.token_next_by(m=(token_types.Keyword, "TABLE")) _, table_identifier = statement.token_next_by(i=token_groups.Identifier, idx=idx) table_name = table_identifier.value deleted_collection = q.select("ref", q.delete(q.collection(table_name))) return [ q.do( q.map_( q.lambda_("ref", q.delete(q.var("ref"))), q.paginate( q.union( q.match( q.index( fql.index_name( "information_schema_tables_", column_name="name_", index_type=fql.IndexType.TERM, )), table_name, ), fql.convert_to_ref_set( "information_schema_columns_", 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], ), ), fql.convert_to_ref_set( "information_schema_indexes_", q.range( q.match( q.index( fql.index_name( "information_schema_indexes_", column_name="table_name_", index_type=fql.IndexType.VALUE, ))), [table_name], [table_name], ), ), ), ), ), q.let( {"collection": deleted_collection}, {"data": [{ "id": q.var("collection") }]}, ), ) ]
def _define_match_set(query_filter: sql.Filter) -> QueryExpression: field_name = query_filter.column.name comparison_value = query_filter.value index_name_for_collection = functools.partial(index_name, query_filter.table_name) convert_to_collection_ref_set = functools.partial(convert_to_ref_set, query_filter.table_name) get_info_indexes_with_references = lambda collection_name, field_name: q.map_( q.lambda_("info_index_ref", q.get(q.var("info_index_ref"))), q.paginate( q.match( q.index( index_name( "information_schema_indexes_", column_name="name_", index_type=IndexType.TERM, )), index_name( collection_name, column_name=field_name, index_type=IndexType.REF, ), ), ), ) index_name_for_field = functools.partial(index_name_for_collection, field_name) equality_range = q.range( q.match(q.index(index_name_for_field(IndexType.VALUE))), [comparison_value], [comparison_value], ) if query_filter.checks_whether_equal: if field_name == "ref": assert isinstance(comparison_value, str) return q.singleton( q.ref(q.collection(query_filter.table_name), comparison_value)) return q.let( { "ref_index": q.index(index_name_for_field(IndexType.REF)), "term_index": q.index(index_name_for_field(IndexType.TERM)), "info_indexes": get_info_indexes_with_references(query_filter.table_name, field_name), "comparison_value": comparison_value, }, q.if_( q.exists(q.var("ref_index")), q.match( q.var("ref_index"), get_foreign_key_ref( q.var("comparison_value"), # Assumes that there is only one reference per foreign key # and that it refers to the associated collection's ID field # (e.g. {'associated_table': 'id'}). # This is enforced via NotSupported errors when creating collections. q.select([0, DATA, "referred_table_"], q.var("info_indexes")), ), ), q.if_( q.exists(q.var("term_index")), q.match( q.var("term_index"), q.var("comparison_value"), ), convert_to_collection_ref_set(equality_range), ), ), ) # In the building of Filter objects from SQL tokens, we enforce the convention # of <column name> <operator> <value> for WHERE clauses, so we build the FQL queries # assuming that '>' means 'column value greater than literal value'. I can't think # of a good way to centralize the knowledge of this convention across # all query translation, so I'm leaving this note as a warning. if query_filter.checks_whether_greater_than: inclusive_comparison_range = q.range( q.match(q.index(index_name_for_field(IndexType.VALUE))), [comparison_value], [], ) return convert_to_collection_ref_set( q.difference(inclusive_comparison_range, equality_range)) if query_filter.checks_whether_greater_than_or_equal: inclusive_comparison_range = q.range( q.match(q.index(index_name_for_field(IndexType.VALUE))), [comparison_value], [], ) return convert_to_collection_ref_set(inclusive_comparison_range) if query_filter.checks_whether_less_than: inclusive_comparison_range = q.range( q.match(q.index(index_name_for_field(IndexType.VALUE))), [], [comparison_value], ) return convert_to_collection_ref_set( q.difference(inclusive_comparison_range, equality_range)) if query_filter.checks_whether_less_than_or_equal: inclusive_comparison_range = q.range( q.match(q.index(index_name_for_field(IndexType.VALUE))), [], [comparison_value], ) return convert_to_collection_ref_set(inclusive_comparison_range) raise exceptions.NotSupportedError( f"Unsupported comparison {query_filter.comparison} was received.")