fix(odata): read an external entity's OData source, and keep its local-changes flag - #60
Merged
Merged
Conversation
) `alter entity X set allow_create_change_locally = true` reported success and left the flag off. So did every other remote setting, and `describe external entity` rejected the entity outright with "is not an external entity (source: )". The write path was never the problem: externalEntitySourceToGen switches on e.Source and handles all three Rest$OData* flavours. The *read* filled none of them — entityFromGen recognised only DomainModels$OqlViewEntitySource, so an external entity came back with an empty Source and every remote field zeroed. Setting a flag then wrote it onto a model that no longer knew the entity was external, and the update rebuilt the entity without its source at all. The legacy engine parses all three flavours (sdk/mpr/parser_domainmodel.go), so this was a modelsdk-engine gap — and modelsdk is the default. Under `--engine legacy` the same commands worked, which is a useful bisect signal. Now mirrored for: - Rest$ODataRemoteEntitySource — service, entity set, remote name, the capability flags, CreateChangeLocally and the remote key - Rest$ODataEntityTypeSource — service, type name, IsOpen and the remote key - Rest$ODataPrimitiveCollectionEntitySource — service Updatable is deliberately left zero: the storage type has no such field (updatability is per attribute via Rest$ODataMappedValue), there is no gen accessor, and the writer does not emit one, so read and write stay symmetric. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XR649rKk68z6gBpngu6MA
…y re-import `create or modify external entities` reset "Allow creating and changing objects locally" to false on every run, so the setting survived only until the next import — the other half of mendixlabs#782. applyExternalEntityFields stamps every field on both the create and the update path. That is right for the capability flags (Countable / Creatable / Deletable / SkipSupported / TopSupported), which are derived from the service's capability annotations and should be refreshed from the metadata. It is wrong for CreateChangeLocally, which no OData contract describes: it is a local modelling choice, so the top-level branch now leaves it alone. A newly imported entity arrives zero-valued, which is Mendix's default. The entity-type branch still clears it, since that storage type has no such field — a re-import that reclassifies an entity as a derived type would otherwise leave a stale value in the model. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XR649rKk68z6gBpngu6MA
…-entity-782 # Conflicts: # .claude/skills/fix-issue.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes
mendixlabs/mxcli#782— "External Entities: allow_create_change_locally doesn't work". Split out of #57.(Issue numbers refer to
mendixlabs/mxcli, not this fork.)It turned out to be two independent bugs, and the first is much bigger than the flag.
The real cause — external entities do not read back
entityFromGenrecognised onlyDomainModels$OqlViewEntitySource, so any OData external entity read back with an emptySourceand every remote field zeroed. The write path was always fine — it switches one.Source, which the read never populated.So
alter entity … set allow_create_change_locally = truewrote the flag onto a model that no longer knew the entity was external, and the update rebuilt the entity without its source at all — losing the entity set, remote name, capabilities and remote key, not just the flag.describe external entitydidn't work either:The bisect signal that nailed it: the same commands work under
--engine legacy, whose parser handles all threeRest$OData*flavours. This is a modelsdk-engine gap, and modelsdk is the default — so anyone on stock mxcli has it.All three flavours are now mirrored from the legacy parser:
ODataRemoteEntitySource(service, entity set, remote name, capability flags,CreateChangeLocally, remote key),ODataEntityTypeSource(service, type name,IsOpen, key) andODataPrimitiveCollectionEntitySource(service).Updatableis deliberately left zero: the storage type has no such field (updatability is per attribute viaRest$ODataMappedValue), there is no gen accessor, and the writer does not emit one — read and write stay symmetric.The half that matches the reporter's words
Even with the read fixed,
create or modify external entitiesreset the flag on every run:applyExternalEntityFieldsstampedCreateChangeLocally = falseon the update path too.That is right for the capability flags (
Countable/Creatable/Deletable/Skip/Top), which the service's capability annotations describe and which should be refreshed from the metadata. It is wrong forCreateChangeLocally, which no OData contract describes — it is a local modelling choice. The top-level branch now leaves it alone; the entity-type branch still clears it, since that storage type has no such field.Testing
make build,make test,make lint,make check-mdlpass on this branch alone.Reproduced the reporter's flow end-to-end against a real project using the repo's own
mdl-examples/odata-local-metadata/sample-metadata.xml. Before:describeerrored, flag stayedNo. After: describe works,alter … = truesticks (confirmed in the raw BSON —CreateChangeLocally: truewith the source and key intact), and a re-import preserves it while still refreshing the contract-derived capabilities.Four round-trip tests in
external_entity_read_test.go, verified failing pre-fix — they also caught the source destruction that the reported symptom hides. Plus a re-import test incmd_contract_test.goand fixture782-external-entity-create-change-locally.mdl.Not included
The bulk
CREATE EXTERNAL ENTITIESstatement still has no syntax to set the flag at import time — you set it afterwards withALTER ENTITY, which now works and survives re-import. Adding import-time syntax would be a grammar change and a separate feature.🤖 Generated with Claude Code
https://claude.ai/code/session_012XR649rKk68z6gBpngu6MA
Generated by Claude Code