srielau commented on PR #58581:
URL: https://github.com/apache/spark/pull/58581#issuecomment-5717198701

   ## Agent working brief (scope freeze)
   
   This PR has been looping because reviews (public GitHub comments and silent 
internal-review commits) keep converting adjacent cases into required work. 
**Do not continue that loop.**
   
   CHAR and VARCHAR are SQL types. Support them where Spark already carries 
ordinary SQL types. Do not invent CHAR/VARCHAR support for every container, 
encoder, or Arrow path that can hold a `DataType`.
   
   ### Mission
   
   Ship **ordinary CHAR/VARCHAR support** through Spark SQL type representation 
and Spark Connect local-relation transport.
   
   ### Success condition
   
   Merge when all of the following are true:
   
   1. A Connect client can `createDataFrame` with CHAR/VARCHAR (uncollated, 
explicit `UTF8_BINARY`, and a non-binary collation).
   2. Logical schema keeps length and collation.
   3. Physical Arrow values are STRING; the client does not apply CHAR padding.
   4. The server applies standard, default, and `legacy.charVarcharAsString` 
policy once, for empty and populated input, identically.
   5. Ordinary nested types work: struct field, array element, map key, map 
value.
   6. Schema JSON for those ordinary cases is readable by the immediately 
preceding JVM reader: uncollated `char(n)`/`varchar(n)` plus ignorable metadata.
   7. Scala and Python agree on encode/decode and on rejection of conflicting 
encodings.
   8. This PR does **not** change ordinary UDT serialization, public 
`StringType` constructor identity, or global Arrow/pandas CHAR/VARCHAR 
acceptance.
   
   If a later review asks for anything outside this list, reply that it is a 
follow-up, do not implement it here, and stop.
   
   ### Fence
   
   A change is in this PR only if all three hold:
   
   1. A user can declare or observe CHAR/VARCHAR through SQL, DataFrame schema, 
or Connect schema.
   2. Classic Spark or established CHAR/VARCHAR semantics are wrong without the 
change.
   3. The fix does not change the contract of an unrelated type or API.
   
   Test question: **Would this still be required if UDTs, pandas, generic Arrow 
UDFs, and explicit ordinary `StringType("UTF8_BINARY")` identity did not 
exist?** If no, it is out of scope.
   
   #### In scope
   
   - CHAR/VARCHAR length and optional collation on the type itself.
   - DDL, JSON, `simpleString`, `repr`, proto, Scala/Python conversion.
   - Ordinary nesting: top-level, struct, array, map.
   - Connect: requested **logical** schema stays CHAR/VARCHAR; **physical** 
encoding uses STRING; server owns policy.
   - Compatibility metadata so old readers parse uncollated CHAR/VARCHAR and 
keep unknown keys.
   - Collision-safety for that metadata key: do not destroy caller metadata.
   - Symmetric Scala/Python validation of that metadata.
   - Reverting regressions this branch introduced (UDT unwrap, global Arrow 
CHAR/VARCHAR, `StringType` sentinel).
   
   #### Out of scope (separate features / follow-up JIRAs)
   
   - CHAR/VARCHAR inside `UserDefinedType.sqlType`, including JSON path 
traversal through UDTs.
   - New UDT serialization/restoration design, except **undoing** a break this 
PR caused.
   - Hidden or public identity of omitted vs explicit `UTF8_BINARY` on ordinary 
`StringType`.
   - Changing `StringType()` constructor default, `__slots__`, or documented 
signature.
   - Global pandas / PyArrow / Arrow UDF acceptance of CHAR/VARCHAR.
   - Exhaustive cached/chunked/pandas/pyarrow.Table matrices unless this PR 
still modifies those paths after the scope reset. If it does, revert the path 
change rather than adding tests to keep it.
   
   ### Required architecture
   
   Keep one contract. Do not grow extra helpers that then need their own 
completeness proofs.
   
   ```text
   Requested SQL schema (logical CHAR/VARCHAR, collations kept)
           |
           +-------------------------------+
           |                               |
           v                               v
   Physical encoding                     Protocol logical schema
   CHAR/VARCHAR -> STRING                CHAR/VARCHAR unchanged
   Do NOT unwrap UDTs                    collations unchanged
   Do NOT serialize via sqlType encoder  empty and populated share this schema
           |                               |
           +------------- server ----------+
                             |
                   apply CHAR/VARCHAR policy once
                             |
                       result schema
   ```
   
   Rules:
   
   - Physical lowering is a **Connect transport detail**, not a global 
`DataType` rewrite.
   - Do not put UDT unwrap inside `DataType.localDataPhysicalType` (or 
equivalent) if user objects still need `UDTEncoder`.
   - Do not make pandas `types.py` treat CHAR/VARCHAR as Arrow strings globally 
in order to fix Connect.
   - Prefer one recursive CHAR/VARCHAR collation codec for struct/array/map in 
both languages. Do not special-case every call site.
   
   ### What to undo on current head
   
   Treat these as scope leaks, not unfinished product work:
   
   1. **`DataType.localDataPhysicalType` UDT unwrap** and JVM `createDataFrame` 
using that physical schema with unmodified user objects. Restore UDT 
serialization. CHAR/VARCHAR lowering to collation-preserving STRING may remain 
**without** unwrapping UDTs.
   2. **Global Arrow mapping** in `python/pyspark/sql/pandas/types.py` and 
generic conversion that makes `VarcharType` Arrow-legal outside Connect. 
Classic `test_err_return_type` must still reject CHAR/VARCHAR if that was prior 
behavior.
   3. **`StringType` `object()` / `_collation_explicit` sentinel.** Revert 
public constructor identity. CHAR/VARCHAR keep `collation=None` vs explicit 
name; ordinary STRING stays as before this PR.
   4. **Tests whose only job is UDT-in-CHAR JSON, pandas/PyArrow 
createDataFrame CHAR, chunked-cache CHAR, or StringType explicitness.** Delete 
them with the features.
   5. **Scalafmt / line-length / json-module shadowing nits** only as needed 
for remaining code. Do not land style-only commits as "review fixes."
   
   Keep:
   
   - Proto optional CHAR/VARCHAR collation fields.
   - `__CHAR_VARCHAR_COLLATIONS` (or one dedicated key) for ordinary nested 
CHAR/VARCHAR, not `__COLLATIONS` on `char(n)` (old JVM rejects that).
   - Logical vs physical Connect split for CHAR/VARCHAR.
   - Server policy for empty and populated, including 
`legacy.charVarcharAsString`.
   - Python CHAR/VARCHAR handled **before** generic `StringType` in JSON (they 
are not Python `StringType` subclasses; do not make them subclasses).
   
   ### Tests that belong here
   
   Invariant tests, not a growing matrix:
   
   - Direct and nested (struct/array/map) CHAR/VARCHAR JSON: omitted collation, 
explicit `UTF8_BINARY`, non-binary collation.
   - Preceding-reader shape: uncollated `char`/`varchar` type strings; 
collation only in the dedicated metadata key.
   - Conflicting inline + metadata encodings rejected in **both** Scala and 
Python.
   - Connect `createDataFrame` empty and one-row, standard / default / 
legacy-as-string.
   - Nested struct/array/map in that Connect path.
   - Caller metadata that already uses the new key is preserved or the write is 
rejected; it must not silently drop or duplicate.
   
   Do not add a test because an agent mentioned a path. Add a test because the 
remaining production code has a branch that this PR still owns.
   
   ### How to handle reviews
   
   There are two agent loops:
   
   1. Public GitHub reviews posted as `cloud-fan` with `SPARK_DEV_REVIEW_CODE` 
markers.
   2. Internal review that produces commits and no PR comments.
   
   Both are optional input, not a backlog you must empty.
   
   For each finding, classify:
   
   | Class | Action |
   |---|---|
   | In-scope correctness bug in remaining CHAR/VARCHAR Connect/JSON code | Fix 
it. |
   | Regression this branch introduced (UDT encode, Arrow UDF, StringType 
signature) | Revert or restore prior behavior. Do not "complete" the new 
behavior. |
   | Adjacent completeness (UDT.sqlType, pandas, chunked, StringType identity) 
| Do not implement. Comment: follow-up, out of fence. |
   | Style/comment/repr-coverage nits on out-of-scope APIs | Ignore or 
follow-up. |
   | "Late catch" that expands the type visitor to a new Spark concept | 
Follow-up unless it is ordinary struct/array/map. |
   
   **Do not run an internal-review pass that implements findings without 
posting the classification.** If you disagree with a finding, say so on the PR 
and stop. Silent fix commits are how this PR ballooned.
   
   Do not force-push unless explicitly asked.
   
   ### Stop conditions (mandatory)
   
   Stop and ask instead of coding when:
   
   - A review demands UDT.sqlType collation JSON or ordinary UDT encode/decode 
redesign.
   - A review demands public `StringType` identity or constructor signature 
changes.
   - A review demands pandas/PyArrow/Arrow-UDF CHAR/VARCHAR as product support.
   - Fixing an in-scope bug seems to require one of the above.
   - You are about to add a new helper whose completeness requires recursion 
through UDTs or global Arrow.
   
   ### Follow-up tickets (mention, do not implement)
   
   1. CHAR/VARCHAR in UDT storage schemas (JSON + encode/decode + Connect).
   2. Explicit vs omitted `UTF8_BINARY` identity for ordinary `StringType`.
   3. First-class Arrow/pandas CHAR/VARCHAR support.
   
   The next change on this branch should **narrow to this fence**, then wait 
for a human before another review-fix cycle.


-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to