Skip to content

Only allow ambiguous path steps between scalar and optional elements#1180

Merged
stevedlawrence merged 1 commit intoapache:mainfrom
stevedlawrence:daffodil-2879-array-optional-ambiguous-path-step
Mar 14, 2024
Merged

Only allow ambiguous path steps between scalar and optional elements#1180
stevedlawrence merged 1 commit intoapache:mainfrom
stevedlawrence:daffodil-2879-array-optional-ambiguous-path-step

Conversation

@stevedlawrence
Copy link
Member

Scalar and optional elements are both implemented in the infoset exactly the same as DIElements, the only real difference is optional elements might not appear in the infoset. Arrays on the other hand are implemented differently as a DIArray. Because of this, it adds complexity if we allow expression path steps that can ambiguously reference either an array or an optional. We currently allow this, but this complexity leads to bugs and thrown exceptions.

In fact, in most cases ambiguously referencing an array or an optional doesn't even work since arrays need a predicate and optionals do not allow predicates. The only case it could potentially work is as the last step as an argument to a function like fn:count. The added complexity is not worth supporting this edge case.

Instead of allowing this, we should instead only allow ambiguous paths steps to scalar and optional elements. This modifies the path step logic to enforce this. A step must now unambiguously reference an array or it must reference scalars/optionals.

Note that this slightly affects the behavior of the fn:count() function. This function must still reference an array or optional as before, but it can now reference a scalar only if it is an ambiguous path that could also reference an optional. If the argument unambiguously references a scalar, it is an SDE as it was before. It can also no longer ambiguously reference an array or optional, but that was previously broken.

DAFFODIL-2879

@stevedlawrence
Copy link
Member Author

@pkatlic, can you take a look at this? This makes a tweak to the changes you made to fn:count

Copy link
Contributor

@tuxji tuxji left a comment

Choose a reason for hiding this comment

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

+1

I expanded the test results diffs to see the tests' comments, and the changes to the results appear to make sense (scalar & optional from ambiguous to good, array & optional from good to ambiguous).

val (arrays, nonArrays) = stepElements.partition { _.isArray }
schemaDefinitionWhen(
arrays.length > 0 && nonArrays.length > 0,
"Path step %s is ambiguous. It can reference both an array or a non-array element, which is not allowed.\n" +
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest changing or to and in the error message above, even though it may cause some tests to require changes to their expected output. When you say "both", that implies "and" rather than "or".

<tdml:error>ex:foo</tdml:error>
<tdml:error>ambiguous</tdml:error>
</tdml:errors>
<tdml:infoset>
Copy link
Contributor

Choose a reason for hiding this comment

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

@pkatlic: As @stevedlawrence asked, please check these changes to test results carefully.

Copy link
Contributor

Choose a reason for hiding this comment

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

The new test results appear to correct the behavior, with scalarOptional parsing properly and arrayOptional throwing the SDE regarding ambiguous path steps.

<!-- throws ClassCastException, possible bug in Daffodil group evaluation -->
<!-- <xs:group ref="countGroup"/> -->
<xs:element name="count" type="xs:int" dfdl:representation="binary" dfdl:inputValueCalc="{ fn:count(../ex:foo) }"/>
<xs:group ref="countGroup"/>
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this now uses the group reference instead of standalone count element.

@pkatlic
Copy link
Contributor

pkatlic commented Mar 12, 2024

+1

The tests now have the expected results for the scalar/optional and array/optional element groups.

Scalar and optional elements are both implemented in the infoset exactly
the same as DIElements, the only real difference is optional elements
might not appear in the infoset. Arrays on the other hand are
implemented differently as a DIArray. Because of this, it adds
complexity if we allow expression path steps that can ambiguously
reference either an array or an optional. We currently allow this, but
this complexity leads to bugs and thrown exceptions.

In fact, in most cases ambiguously referencing an array or an optional
doesn't even work since arrays need a predicate and optionals do not
allow predicates. The only case it could potentially work is as the last
step as an argument to a function like fn:count. The added complexity is
not worth supporting this edge case.

Instead of allowing this, we should instead only allow ambiguous paths
steps to scalar and optional elements. This modifies the path step logic
to enforce this. A step must now unambiguously reference an array or it
must reference scalars/optionals.

Note that this slightly affects the behavior of the fn:count() function.
This function must still reference an array or optional as before, but
it can now reference a scalar only if it is an ambiguous path that could
also reference an optional. If the argument unambiguously references a
scalar, it is an SDE as it was before. It can also no longer ambiguously
reference an array or optional, but that was previously broken.

DAFFODIL-2879
@stevedlawrence stevedlawrence force-pushed the daffodil-2879-array-optional-ambiguous-path-step branch from 0754845 to e08ee67 Compare March 14, 2024 11:45
@stevedlawrence stevedlawrence merged commit 3f897fe into apache:main Mar 14, 2024
@stevedlawrence stevedlawrence deleted the daffodil-2879-array-optional-ambiguous-path-step branch March 14, 2024 12:20
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.

3 participants