eugenegujing opened a new issue, #7925:
URL: https://github.com/apache/texera/issues/7925

   ### What happened?
   
   The Projection operator's "Drop Option" (`isDrop = true`) computes "which 
attributes to remove" in two places that disagree on whether attribute names 
are case-sensitive.
   
   The descriptor derives the output schema through `Schema.remove`, which 
lowercases both sides before comparing:
   
   ```scala
   // 
common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/projection/ProjectionOpDesc.scala:67-71
           } else {
             attributes.foldLeft(inputSchema) { (schema, attribute) =>
               schema.remove(attribute.getOriginalAttribute)
             }
           }
   ```
   
   ```scala
   // 
common/workflow-core/src/main/scala/org/apache/texera/amber/core/tuple/Schema.scala:170-174
     def remove(attributeNames: Iterable[String]): Schema = {
       val attributesToRemove = attributeNames.map(_.toLowerCase).toSet
   ```
   
   The executor computes the kept set with `List.diff`, which compares names 
exactly:
   
   ```scala
   // 
common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/projection/ProjectionOpExec.scala:40-43
       if (desc.isDrop) {
         val allAttribute = tuple.schema.getAttributeNames
         val selectedAttributes = desc.attributes.map(_.getOriginalAttribute)
         val keepAttributes = allAttribute.diff(selectedAttributes)
   ```
   
   So for an input schema containing `field1` and a drop entry spelled 
`Field1`: the descriptor removes `field1` from the declared output schema, 
while the executor's `diff` does not match it and `project()` keeps it. A 
genuinely misspelled attribute fails at plan time (`Schema.remove` throws on 
non-existent names), but a merely differently-cased one passes that check and 
diverges silently at runtime.
   
   The divergence does not reach downstream operators in the current engine: 
`DataProcessor` re-projects the executor's `MapTupleLike` onto the declared 
port schema by attribute name, which discards the extra field, so the 
end-to-end output happens to match the declared schema. The inconsistency is 
internal to the operator, and end-to-end correctness currently depends on that 
name-based re-projection rather than on the two halves agreeing. The `Schema` 
class is otherwise uniformly case-insensitive (`getIndex`, `containsAttribute`, 
`add`, `remove` all lowercase before comparing); the executor's raw `diff` is 
the outlier.
   
   The executor-side behavior is pinned by the drop-mode spec `"match drop 
names case-sensitively"` in `ProjectionOpExecSpec`, whose comment notes that it 
diverges from the descriptor.
   
   ### How to reproduce?
   
   Reproducible at the unit level, against a schema with attributes `field1`, 
`field2`, `field3`:
   
   1. Configure a `ProjectionOpDesc` with `isDrop = true` and a single drop 
entry spelled `FIELD2`.
   2. Derive the output schema through the descriptor: `Schema.remove` matches 
case-insensitively, so the declared output schema is `field1`, `field3`.
   3. Feed one tuple through `ProjectionOpExec.project` with the same 
configuration: the executor's `diff` matches exactly, finds no attribute named 
`FIELD2`, and the returned tuple still contains all three fields — including 
the `field2` the declared schema removed.
   
   The existing spec `"match drop names case-sensitively"` in 
`ProjectionOpExecSpec` runs exactly step 3 and pins its result, so running that 
spec is the fastest way to see the divergence.
   
   There are no end-to-end steps because the divergence is not observable from 
a running workflow: creating the case-mismatched configuration requires 
bypassing the UI in the first place (the attribute picker autofills exact 
names, so it takes a hand-edited or imported workflow JSON, or an upstream 
schema whose casing changed after the operator was configured), and even then 
the engine re-projects the executor's output onto the declared schema before it 
reaches downstream operators or storage, so the final result looks correct 
regardless.
   
   ### Version/Branch
   
   1.3.0-incubating-SNAPSHOT (main)
   
   ### Commit Hash (Optional)
   
   _No response_
   
   ### What browsers are you seeing the problem on?
   
   _No response_
   
   ### Relevant log output
   
   ```shell
   
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to