Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions specifyweb/backend/stored_queries/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,29 @@ def lookup_name(name: str) -> Element | None:
return None

def getFormatterFromSchema() -> Element:

try:
formatter_name = Splocalecontainer.objects.get(
name=specify_model.name.lower(),
schematype=0,
discipline=self.collection.discipline
).format
except Splocalecontainer.DoesNotExist:
containers = Splocalecontainer.objects.filter(
name=specify_model.name.lower(),
schematype=0,
discipline=self.collection.discipline,
).order_by('-timestampmodified', '-id')
container_count = containers.count()
if container_count == 0:
return None

formatter_name = (
containers.exclude(format__isnull=True)
.exclude(format='')
.values_list('format', flat=True)
.first()
)
if container_count > 1:
logger.warning(
"Multiple Splocalecontainer rows found for %s in discipline %s using formatter %r",
specify_model.name.lower(),
self.collection.discipline_id,
formatter_name,
)

if formatter_name:
return lookup_name(formatter_name)
else:
Expand Down
71 changes: 71 additions & 0 deletions specifyweb/backend/trees/tests/test_trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,77 @@ def _run_for_row():
]
self.assertCountEqual(results, expected)

def test_taxon_rows_include_author_and_synonyms(self):
root = self.make_taxontree(
"Life",
"Taxonomy Root",
definition=self.taxontreedef,
)
animalia = self.make_taxontree(
"Animalia",
"Kingdom",
definition=self.taxontreedef,
parent=root,
author="L.",
)
metazoa = self.make_taxontree(
"Metazoa",
"Kingdom",
definition=self.taxontreedef,
parent=root,
acceptedtaxon=animalia,
fullname="Metazoa",
author="Haeckel",
)
animalia.refresh_from_db()
metazoa.refresh_from_db()

@contextmanager
def _run_for_row():
with TreeViewsTest.test_session_context() as session:
set_group_concat_max_len(connection.cursor())
yield session

with _run_for_row() as session:
results = get_tree_rows(
self.taxontreedef.id,
"Taxon",
root.id,
"name",
True,
session,
)
expected = [
(
animalia.id,
animalia.name,
animalia.fullname,
animalia.nodenumber,
animalia.highestchildnodenumber,
animalia.rankid,
None,
None,
animalia.author,
0,
metazoa.fullname,
),
(
metazoa.id,
metazoa.name,
metazoa.fullname,
metazoa.nodenumber,
metazoa.highestchildnodenumber,
metazoa.rankid,
animalia.id,
animalia.fullname,
metazoa.author,
0,
None,
),
]

self.assertCountEqual(results, expected)


class AddDeleteRankResourcesTest(ApiTests):
def test_add_ranks_without_defaults(self):
Expand Down
57 changes: 29 additions & 28 deletions specifyweb/backend/trees/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,44 +182,45 @@ def get_tree_rows(treedef, tree, parentid, sortfield, include_author, session):

treedef_col = getattr(node, tree_table.name + "TreeDefID")
orderby = getattr(node, tree_table.get_field_strict(sortfield).name)
child_counts = (
select(
child.ParentID.label("parent_id"),
func.count(child._id).label("child_count"),
)
.group_by(child.ParentID)
.subquery()
)
synonym_names = (
select(
synonym.AcceptedID.label("accepted_id"),
group_concat(distinct(synonym.fullName), separator=", ").label("synonyms"),
)
.where(synonym.AcceptedID.is_not(None))
.group_by(synonym.AcceptedID)
.subquery()
)

# We use min for grouped columns because for some reason, SQL is rejecting
# the group_by in some dbs due to "only_full_group_by". It is somehow not
# smart enough to see that there is no dependency in the columns going from
# main table to the to-manys (child, and syns).
# I want to use ANY_VALUE() but that's not supported by MySQL 5.6- and MariaDB.
# I don't want to disable "only_full_group_by" in case someone misuses it...
# applying min to fool into thinking it is aggregated.
# these values are guarenteed to be the same
cols = [
node._id.label("id"),
func.min(node.name).label("name"),
func.min(node.fullName).label("full_name"),
func.min(node.nodeNumber).label("node_number"),
func.min(node.highestChildNodeNumber).label("highest_child_number"),
func.min(node.rankId).label("rank_id"),

func.min(node.AcceptedID).label("accepted_id"),
func.min(accepted.fullName).label("accepted_fullname"),

(
func.min(node.author)
if include_author
else func.min(literal("NULL"))
).label("author"),

func.count(distinct(child._id)).label("child_count"),
group_concat(distinct(synonym.fullName), separator=", ").label("synonyms"),
node.name.label("name"),
node.fullName.label("full_name"),
node.nodeNumber.label("node_number"),
node.highestChildNodeNumber.label("highest_child_number"),
node.rankId.label("rank_id"),
node.AcceptedID.label("accepted_id"),
accepted.fullName.label("accepted_fullname"),
(node.author if include_author else literal("NULL")).label("author"),
func.coalesce(child_counts.c.child_count, 0).label("child_count"),
synonym_names.c.synonyms.label("synonyms"),
]

query = (
select(*cols)
.outerjoin(child, child.ParentID == node._id)
.outerjoin(accepted, node.AcceptedID == accepted._id)
.outerjoin(synonym, synonym.AcceptedID == node._id)
.outerjoin(child_counts, child_counts.c.parent_id == node._id)
.outerjoin(synonym_names, synonym_names.c.accepted_id == node._id)
.where(treedef_col == int(treedef))
.where(node.ParentID == parentid)
.group_by(node._id)
.order_by(orderby)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,7 @@ export const notificationRenderers: IR<
);
},
'collection-creation-starting'() {
return (
<p>{setupToolText.collectionCreationStarted()}</p>
);
return <p>{setupToolText.collectionCreationStarted()}</p>;
},
default(notification) {
console.error('Unknown notification type', { notification });
Expand Down
Loading
Loading