Move GraphSteps to HashMultiset
Move GraphStep to HashMultimap
Activate REAP logic on all tables (Fix #11000)

Since REAP was not being properly passed down the
tree of GraphSteps, this commit considers any row
that is to be re-checked (i.e. is present in the
reapTableIds map) to be SOFT. In other words, a
failure for a row that will be processed again
later on does not constitute a hard failure.

Note: this is not necessarily strictly valid in
all cases. A row is in 2 separate subtrees, then
really it should be checked if the entire subtree
is to be re-checked. That logic may have to wait
for a revamp of the ome.services.graph package.

Tested via CMU-1 and openmicroscopy/bioformats#536
Disable the CHGRP-VALIDATION event logs

They don't represent an actual change to the data
and therefore serve little or not purpose.
Passing test in chgrp.py (See #11000)
Show GraphConstraintERR.constraints in library.py
Add ExtendedMetadata.getSQLJoin (See #11054)

In order to make use of `select distinct on (...)`, the
ome.services.graph package needs to be able to drop down
into raw SQL rather than HQL. Doing so, loses all of the
HQL dot notation, meaning it's necessary to lookup the
SQL-style joins for walking the graph.

This isn't a complete solution in that it doesn't take
joined subclasses into account, but works for the current
uses.
Add support for positional parameters to QueryBuilder

Use of direct SQL seemed to be returning odd results.
Positional params may or may not have helped with that
issue, but since they are implemented it doesn't hurt
to leave them. Named parameters should likely still be
preferred throughout the code base.
Permit 'select distinct on' raw SQL (See #11054, #9496)

Previously, only UPDATE and DELETE statements were allowed.
HQL, however, does not properly support `distinct on (...)`
and therefore it was necessary to include this workaround.
Refactor NULL handling into GraphStep (See #11054)

In preparation for NULLing UploadJob.versionInfo as a
workaround for SQL joined-subclass handling, the delete
step logic for nulling Pixels.relatedTo must be expanded
to also handle nulling versionInfo including during chgrp.
Refactor queryBackupIds for re-use by subclasses

The upcoming FilesetGraphSpec will need access to individual
parts of the queryBackupIds method. This is now been split up
into several protected methods for re-use.
Add FilesetGraphSpec to solve performance issues (Fix #11054)

"select distinct on (...)" is used to only load a /Fileset
once for an entire subgraph. To handle the variable intermediate
links, `-2` is inserted into the array of IDs, so that matching
in GraphTables completes appropriately.

/Filesets are now only handled from the contain types /Plate
and /Dataset.

NB: this is still not working because the super spec which
wraps the FilesetGraphSpec is not performing the proper
logic.
Attempt to workaround missing Filesets
Revert "Attempt to workaround missing Filesets"

This reverts commit ab7184331855e37eec4b8e84aef929e86051ceb4.
Attempt to use synthetic paths e.g. /Dataset/Fileset

Since the dropped values between Dataset and Fileset seem
to be confusing the GraphTables logic (leading to duplicates
and similar), this change attempts to act as if the two
objects are actually related. Note: this does *not* require
SQL as the previous attempt did.
Move HQL distinct workaround for synthetics to base class

Since all the calls will need proper handling, move all logic
back to BaseGraphSpec.
Tweaking spec.xml for various tests
Extend BaseGraphSpec workaround for PDI, etc
Use DoAll even with single-image filesets (See #11054)

Since preprocessing is necessary in order to handle Filesets
rather than images, all chgrps that are not via a container
should take place via a DoAll.
Comment suggestion from Mark