Skip to content

GitHub Issue 903: Remove Cross-Container Sample and Data Class Import Feature#7698

Open
XingY wants to merge 11 commits into
developfrom
fb_dropCrossFolder
Open

GitHub Issue 903: Remove Cross-Container Sample and Data Class Import Feature#7698
XingY wants to merge 11 commits into
developfrom
fb_dropCrossFolder

Conversation

@XingY
Copy link
Copy Markdown
Contributor

@XingY XingY commented May 26, 2026

Rationale

This PR removes the support for cross-container sample and data class import feature. The feature allowed import of samples and data class rows belonging to other folders in a single file, which was implemented via temp partitioned files, which is error-prone. Attempts to update/merge rows that does not exist in the current container now generate a generic error message ("Sample/Data does not exist in : "), without revealing its existence in other folders.

Related Pull Requests

Changes

  • Fixed issue that orphaned exp.material record is created when merging a sample in a container that user lacks read permission to
  • Remove crossFolderImport from DataIteratorContext and AbstractQueryImportAction.Params
  • Remove stale QueryUpdateService.hasExistingRowsInOtherContainers
  • Remove DefaultQueryUpdateService.configureCrossFolderImport
  • Remove cross-folder partitioning, folder-column detection, and per-container split-file logic from MultiDataTypeCrossProjectDataIterator
  • Container/Folder columns are now always dropped during sample and data class import (previously they were conditionally kept for cross-folder merges)
  • SampleTypeUpdateServiceDI.getExistingRows: use ElevatedUser when searching other containers for cross-container existence checks, so samples are not missed due to the requesting user's limited read permissions
  • ExpDataClassDataTableImpl._select: add ClassId to the RowId filter to avoid returning a row from a different data class with the same RowId; add fallback lookup against exp.data when allowCrossContainer is true to account for data filtered out due to user's permission
  • Standardize "not found" error messages across samples and data classes for data present in an folder without permission and data don't exist anywhere

Map<Integer, Map<String, Object>> result = new LinkedHashMap<>();
for (Map.Entry<Integer, Map<String, Object>> key : keys.entrySet())
{
String keyDisplay = key.getValue().toString();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Perhaps just inline so we only need to compute once when there is an error.

return false;
}

protected void configureCrossFolderImport(DataIteratorBuilder rows, DataIteratorContext context) throws IOException
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: (unrelated) unused imports

const server = hookServer(process.env);
const PROJECT_NAME = 'DataClassCrudJestProject';
const PROJECT_NAME = 'AssayDesignCrudJestProject';
console.log(`[AssayDesignCrud] Random seed: ${testSeed} (rerun with: TEST_SEED=${testSeed})`);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we console log this during init() in integrationUtils.ts like we do the server and container path? Then each test would not need to log it themselves.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, it's already logged in init(). I decided to also log it individually for ease of locating the seed as teamcity build log could get long and/or corrupted.

private final TSVWriter _tsvWriter;

private MultiDataTypeCrossProjectDataIterator(DataIterator di, DataIteratorContext context, Container container, User user, boolean isCrossType, boolean isCrossFolder, ExpObject dataType, boolean isSamples)
private MultiDataTypeCrossProjectDataIterator(DataIterator di, DataIteratorContext context, Container container, User user, boolean isCrossType, ExpObject dataType, boolean isSamples)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels good to reduce complexity.

if (foundId.isPresent())
{
index = map.get(foundId.get());
dataKey = RowId.fieldKey();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports


if (dataRow == null && allowCrossContainer)
{
// data not found from queryTable but exist in exp.data, which happens when users lack of permission to data's container
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite follow. Shouldn't the row in the queryTable's container always align with the container of the exp.data? Isn't it the same thing, hence why we don't have a container column on the provisioned table?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

queryTable is a filtered ContainerFilterable table with container filter for the DataClassData table, that checks for user's permission. ExperimentService.get().getTinfoData()returns a SchemaTableInfo, that doesn't care about user, nor container.

{
// data not found from queryTable but exist in exp.data, which happens when users lack of permission to data's container
selector = new TableSelector(ExperimentService.get().getTinfoData(), filter, null);
try (var results = selector.getResults())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this use exists()?

if (dataRow == null && allowCrossContainer)
{
    // data not found from queryTable but exist in exp.data, which happens when users lack of permission to data's container
    if (new TableSelector(ExperimentService.get().getTinfoData(), Collections.singleton(ExpDataTable.Column.RowId.name()), filter, null).exists())
    {
        String keyDisplay = name != null ? name : (rowId != null ? "{RowId=" + rowId + "}" : lsid);
        throw new InvalidKeyException("Data does not exist in " + container.getName() + ": " + keyDisplay + ".");
    }
}

nit: Just select the RowId column.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants