diff --git a/edb/schema/indexes.py b/edb/schema/indexes.py index bbcc21e07c3..08e2863a7e4 100644 --- a/edb/schema/indexes.py +++ b/edb/schema/indexes.py @@ -71,21 +71,19 @@ def is_index_valid_for_type( schema: s_schema.Schema, context: sd.CommandContext, ) -> bool: - index_name = str(index.get_name(schema)) + index_allows_tuples = is_index_supporting_tuples(index, schema) for index_match in schema.get_referrers( index, scls_type=IndexMatch, field_name='index', ): valid_type = index_match.get_valid_type(schema) - if index_name == 'std::fts::index': - # FTS index works not only on its valid type (document), but also - # on tuples comtaining document as an element. + if index_allows_tuples: if is_subclass_or_tuple(expr_type, valid_type, schema): return True elif expr_type.issubclass(schema, valid_type): return True - if context.testmode and index_name == 'default::test': + if context.testmode and str(index.get_name(schema)) == 'default::test': # For functional tests of abstract indexes. return expr_type.issubclass( schema, @@ -95,6 +93,21 @@ def is_index_valid_for_type( return False +def is_index_supporting_tuples( + index: Index, + schema: s_schema.Schema, +) -> bool: + index_name = str(index.get_name(schema)) + return index_name in { + "std::fts::index", + "ext::pg_trgm::gin", + "ext::pg_trgm::gist", + "pg::gist", + "pg::gin", + "pg::brin", + } + + def is_subclass_or_tuple( ty: s_types.Type, parent: s_types.Type, schema: s_schema.Schema ) -> bool: diff --git a/tests/schemas/pg_trgm.esdl b/tests/schemas/pg_trgm.esdl index aee13d97f08..96fae0e80d6 100644 --- a/tests/schemas/pg_trgm.esdl +++ b/tests/schemas/pg_trgm.esdl @@ -26,6 +26,16 @@ type Gin extending Base { index ext::pg_trgm::gin on (.p_str); } +type Gin2 extending Base { + p_str_2: str; + index ext::pg_trgm::gist on ((.p_str, .p_str_2)); +} + type Gist extending Base { index ext::pg_trgm::gist on (.p_str); } + +type Gist2 extending Base { + p_str_2: str; + index ext::pg_trgm::gist on ((.p_str, .p_str_2)); +} diff --git a/tests/schemas/pg_trgm_setup.edgeql b/tests/schemas/pg_trgm_setup.edgeql index 0069f1fae18..ab1d2ae48f5 100644 --- a/tests/schemas/pg_trgm_setup.edgeql +++ b/tests/schemas/pg_trgm_setup.edgeql @@ -18,7 +18,14 @@ for x in range_unpack(range(1, 1001)) union ( insert Gist { - p_str := "qwertyu" ++ str_pad_start(x, 4, "0") + p_str := "qwertyu" ++ str_pad_start(x, 4, "0"), + } +); + +for x in range_unpack(range(1, 1001)) union ( + insert Gist2 { + p_str := "qwertyu" ++ str_pad_start(x, 4, "0"), + p_str_2 := "iopasdf" ++ str_pad_start(x, 4, "0"), } ); @@ -531,7 +538,12 @@ for x in { "Samarra School", "Jangal-e Marakeh Sar", } union ( - insert Gist { + (insert Gist { p_str := x - } + }) + union + (insert Gist2 { + p_str := x, + p_str_2 := x, + }) ); diff --git a/tests/test_edgeql_ext_pg_trgm.py b/tests/test_edgeql_ext_pg_trgm.py index 098fa2f81ff..139e482fa35 100644 --- a/tests/test_edgeql_ext_pg_trgm.py +++ b/tests/test_edgeql_ext_pg_trgm.py @@ -129,6 +129,47 @@ async def test_edgeql_ext_pg_trgm_similarity(self): index_type="ext::pg_trgm::gist", ) + qry = """ + SELECT + Gist2 { + p_str, + sim_dist := ext::pg_trgm::similarity_dist( + .p_str, "q0987wertyu0988" + ), + p_str_2, + sim_dist_2 := ext::pg_trgm::similarity_dist( + .p_str_2, "q0987opasdf0988" + ), + } + ORDER BY + .sim_dist EMPTY LAST THEN .sim_dist_2 EMPTY LAST + LIMIT + 2 + """ + + await self.assert_query_result( + qry, + [ + { + "p_str": "qwertyu0988", + "sim_dist": 0.411765, + "p_str_2": "iopasdf0988", + "sim_dist_2": 0.5, + }, + { + "p_str": "qwertyu0987", + "sim_dist": 0.5, + "p_str_2": "iopasdf0987", + "sim_dist_2": 0.57894737, + }, + ] + ) + + await self.assert_index_use( + qry, + index_type="ext::pg_trgm::gist", + ) + async def test_edgeql_ext_pg_trgm_word_similarity(self): await self.assert_query_result( """ @@ -216,6 +257,43 @@ async def test_edgeql_ext_pg_trgm_word_similarity(self): index_type="ext::pg_trgm::gist", ) + qry = """ + SELECT + Gist2 { + p_str, + word_sim_dist := ext::pg_trgm::word_similarity_dist( + "Kabankala", .p_str + ), + p_str_2, + word_sim_dist_2 := ext::pg_trgm::word_similarity_dist( + "Pub", .p_str_2 + ) + } + ORDER BY + .word_sim_dist EMPTY LAST THEN .word_sim_dist_2 EMPTY LAST + LIMIT + 2 + """ + + await self.assert_query_result( + qry, + [ + { + "p_str": "Kabankala", + "word_sim_dist": 0.0, + }, + { + "p_str": "Kabankalan City Public Plaza", + "word_sim_dist": 0.1, + }, + ] + ) + + await self.assert_index_use( + qry, + index_type="ext::pg_trgm::gist", + ) + async def test_edgeql_ext_pg_trgm_strict_word_similarity(self): await self.assert_query_result( """