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
1 change: 1 addition & 0 deletions .github/workflows/multiTenancyDeployLocal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ jobs:
echo "java version:"
java --version
sed -i 's|__REPOSITORY_ID__|${{ steps.set_repository_id.outputs.repository_id }}|g' mta.yaml
sed -i 's|__DATABASE_ID__|${{ secrets.DATABASE_ID }}|g' mta.yaml
mbt build
echo "✅ MBT build completed!"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ jobs:
echo "java version:"
java --version
sed -i 's|__REPOSITORY_ID__|${{ steps.set_repository_id.outputs.repository_id }}|g' mta.yaml
sed -i 's|__DATABASE_ID__|${{ secrets.DATABASE_ID }}|g' mta.yaml
mbt build
echo "✅ MBT build completed!"

Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
sdm/target/
**/target/
.flattened-pom.xml
node_modules/
**/package-lock.json
**/src/gen/

# Compiled class file
*.class
Expand All @@ -22,6 +25,12 @@ node_modules/
*.zip
*.tar.gz
*.rar
*.hdbtable
*.hdbview
*.xml
*.json
*.sql
*.mtar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ modules:
parameters:
memory: 256M
disk-quota: 1024M
properties:
DATABASE_ID: __DATABASE_ID__ # Placeholder for DATABASE_ID
build-parameters:
builder: custom
build-result: gen
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const cds = require('@sap/cds');

const LOG = cds.log('server');

cds.once('bootstrap', async (app) => {
const databaseId = process.env.DATABASE_ID;
if (databaseId && databaseId !== 'REPLACE_WITH_YOUR_DATABASE_ID') {
cds.env.requires['cds.xt.DeploymentService'] ??= {};
cds.env.requires['cds.xt.DeploymentService'].hdi ??= {};
cds.env.requires['cds.xt.DeploymentService'].hdi.create ??= {};
cds.env.requires['cds.xt.DeploymentService'].hdi.create.database_id = databaseId;
LOG.info(`Configured HDI database_id from environment`);
} else {
LOG.error(`DATABASE_ID environment variable is not set or is still the placeholder. HDI container creation will fail.`);
}
});

module.exports = cds.server;
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ modules:
parameters:
memory: 256M
disk-quota: 1024M
properties:
DATABASE_ID: __DATABASE_ID__ # Placeholder for DATABASE_ID
build-parameters:
builder: custom
build-result: gen
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const cds = require('@sap/cds');

const LOG = cds.log('server');

cds.once('bootstrap', async (app) => {
const databaseId = process.env.DATABASE_ID;
if (databaseId && databaseId !== 'REPLACE_WITH_YOUR_DATABASE_ID') {
cds.env.requires['cds.xt.DeploymentService'] ??= {};
cds.env.requires['cds.xt.DeploymentService'].hdi ??= {};
cds.env.requires['cds.xt.DeploymentService'].hdi.create ??= {};
cds.env.requires['cds.xt.DeploymentService'].hdi.create.database_id = databaseId;
LOG.info(`Configured HDI database_id from environment`);
} else {
LOG.error(`DATABASE_ID environment variable is not set or is still the placeholder. HDI container creation will fail.`);
}
});

module.exports = cds.server;
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,30 @@ public static List<String> getAttachmentEntityPaths(
}

/**
* Creates a mapping of attachment entity paths to their corresponding actual paths within the CDS
* model.
* Creates a mapping of direct attachment entity paths for the given CDS entity.
*
* <p>This method analyzes both direct and nested attachment compositions within the given entity.
* It processes direct attachments that are immediate compositions of the entity, and also
* traverses nested compositions to find attachments in related entities. The resulting mapping
* provides a translation between logical attachment paths and their actual implementation paths.
* <p>This method processes only direct attachment compositions (immediate compositions of the
* entity that target sap.attachments.Attachments). Nested compositions are not traversed.
*
* @param model the CDS model containing entity definitions and relationships
* @param entity the target CDS entity to analyze for attachment path mappings
* @param persistenceService the persistence service used for data access operations
* @return a map where keys are attachment entity paths and values are the corresponding actual
* paths, or an empty map if no attachments are found or if an error occurs during processing
* @param entity the target CDS entity to analyze for direct attachment path mappings
* @return a map where keys and values are the direct attachment entity paths, or an empty map if
* no direct attachments are found
*/
public static Map<String, String> getDirectAttachmentPathMapping(CdsEntity entity) {
logger.debug(
"Getting direct attachment path mapping for entity: {}", entity.getQualifiedName());
Map<String, String> pathMapping = new HashMap<>();
entity
.compositions()
.forEach(
composition -> processDirectAttachmentComposition(entity, pathMapping, composition));
logger.debug(
"Found {} direct attachment path mappings for entity: {}",
pathMapping.size(),
entity.getQualifiedName());
return pathMapping;
}

public static Map<String, String> getAttachmentPathMapping(
CdsModel model, CdsEntity entity, PersistenceService persistenceService) {
logger.debug("Getting attachment path mapping for entity: {}", entity.getQualifiedName());
Expand Down
48 changes: 26 additions & 22 deletions sdm/src/main/java/com/sap/cds/sdm/persistence/DBQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -568,37 +568,41 @@ public CmisDocument getuploadStatusForAttachment(
String objectId,
AttachmentReadEventContext context) {
logger.debug("Fetching uploadStatus for objectId: {} from entity: {}", objectId, entity);
Optional<CdsEntity> attachmentEntity = context.getModel().findEntity(entity + "_drafts");
CqnSelect q =
Select.from(attachmentEntity.get())
.columns("uploadStatus")
.where(doc -> doc.get("objectId").eq(objectId));
Result result = persistenceService.run(q);
CmisDocument cmisDocument = new CmisDocument();
boolean isAttachmentFound = false;
for (Row row : result.list()) {
cmisDocument.setUploadStatus(
row.get("uploadStatus") != null
? row.get("uploadStatus").toString()
: SDMConstants.UPLOAD_STATUS_IN_PROGRESS);
isAttachmentFound = true;
}
if (!isAttachmentFound) {
logger.debug(
"Attachment not found in draft table for objectId: {}, checking active entity: {}",
objectId,
entity);
attachmentEntity = context.getModel().findEntity(entity);
q =
Select.from(attachmentEntity.get())
Optional<CdsEntity> draftEntityOpt = context.getModel().findEntity(entity + "_drafts");
if (draftEntityOpt.isPresent()) {
CqnSelect q =
Select.from(draftEntityOpt.get())
.columns("uploadStatus")
.where(doc -> doc.get("objectId").eq(objectId));
result = persistenceService.run(q);
Result result = persistenceService.run(q);
for (Row row : result.list()) {
cmisDocument.setUploadStatus(
row.get("uploadStatus") != null
? row.get("uploadStatus").toString()
: SDMConstants.UPLOAD_STATUS_IN_PROGRESS);
isAttachmentFound = true;
}
}
if (!isAttachmentFound) {
logger.debug(
"Attachment not found in draft table for objectId: {}, checking active entity: {}",
objectId,
entity);
Optional<CdsEntity> activeEntityOpt = context.getModel().findEntity(entity);
if (activeEntityOpt.isPresent()) {
CqnSelect q =
Select.from(activeEntityOpt.get())
.columns("uploadStatus")
.where(doc -> doc.get("objectId").eq(objectId));
Result result = persistenceService.run(q);
for (Row row : result.list()) {
cmisDocument.setUploadStatus(
row.get("uploadStatus") != null
? row.get("uploadStatus").toString()
: SDMConstants.UPLOAD_STATUS_IN_PROGRESS);
}
}
}
logger.debug(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,18 +187,13 @@ public void handleDraftDiscardForLinks(DraftCancelEventContext context) throws I
logger.debug("Processing draft cancel for entity: {}", parentEntityName);

Optional<CdsEntity> parentActiveEntityOpt = context.getModel().findEntity(parentEntityName);
Map<String, String> compositionPathMapping =
parentActiveEntityOpt
.map(
cdsEntity ->
AttachmentsHandlerUtils.getAttachmentPathMapping(
context.getModel(), cdsEntity, persistenceService))
.orElse(new HashMap<>());

logger.debug("Found {} composition paths to process", compositionPathMapping.size());
for (Map.Entry<String, String> entry : compositionPathMapping.entrySet()) {
String attachmentCompositionDefinition = entry.getKey();
revertLinksForComposition(context, parentKeys, attachmentCompositionDefinition);
if (parentActiveEntityOpt.isPresent()) {
Map<String, String> compositionPathMapping =
AttachmentsHandlerUtils.getDirectAttachmentPathMapping(parentActiveEntityOpt.get());
logger.debug("Found {} composition paths to process", compositionPathMapping.size());
for (Map.Entry<String, String> entry : compositionPathMapping.entrySet()) {
revertLinksForComposition(context, parentKeys, entry.getKey());
}
}
revertNestedEntityLinks(context);
logger.debug("END: Handle draft discard for links");
Expand Down Expand Up @@ -697,7 +692,13 @@ private void checkAttachmentConstraints(
throws ServiceException {
logger.debug("Checking attachment constraints for upID: {}", upID);
CdsModel cdsModel = context.getModel();
CdsEntity attachmentEntity = cdsModel.findEntity(context.getTarget().getQualifiedName()).get();
CdsEntity attachmentEntity =
cdsModel
.findEntity(context.getTarget().getQualifiedName())
.orElseThrow(
() ->
new ServiceException(
"Entity not found in model: " + context.getTarget().getQualifiedName()));

// Fetch the row count for current repository
Result result =
Expand Down
Loading
Loading