Fix Row unpickling for long values that fit in int - #1247
Fix Row unpickling for long values that fit in int#1247mmustafasenoglu wants to merge 4 commits into
Conversation
When PySpark serializes a long value that fits in an int, the Pickler optimizes it and serializes as int. When .NET deserializes this boxed int, a direct unbox to long (or GetAs<long>) throws an exception. Fix by adding NeedConversion() + FromInternal() to LongType, IntegerType, and ShortType so Row.Convert() coerces the unpickled value to match the schema type. This follows the same pattern already used by TimestampType. Also adds a test that reproduces the exact scenario from issue dotnet#27.
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
@dotnet-policy-service agree |
|
/AzurePipelines run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
@dotnet-policy-service agree |
|
@mmustafasenoglu The remaining behavior introduced by this PR is eager normalization of The current pipeline also fails because Could you please:
Once the pipeline is green, we can review the narrowed change again. |
Addresses review feedback on dotnet#1247: - Remove NeedConversion/FromInternal from IntegerType and ShortType (integer values already unpickle as System.Int32, conversion is unnecessary and breaks ArrayType<IntegerType>/MapType<IntegerType>) - Keep LongType coercion (the actual fix for dotnet#27) - Add RowLongTypeInArrayTest and RowLongTypeInMapTest for nested cases - LongType.FromInternal returns the original object when already long to avoid re-boxing
|
Addressed review feedback:
All 3 new tests pass locally. Pipeline should be green now. |
|
Thanks for narrowing the change to LongType and adding the array/map coverage. |
When obj is already a boxed long, return obj directly instead of unboxing to primitive long and re-boxing. This avoids unnecessary allocation on the hot path. Add Assert.Same test for already boxed long in RowTests.
…PickledIntTest Verifies that when a boxed long is passed directly (not pickled as int), it's returned as-is without re-boxing.
|
/AzurePipelines run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Closes #27
When PySpark serializes a long value that fits in an int, the Pickler optimizes it and serializes as int. When .NET deserializes this boxed int, a direct unbox to long (or
GetAs<long>()) throws an exception because the boxed type isint, notlong.This is exactly the scenario described in the issue —
TimestampType.FromInternal()already has a workaround for this, butLongTypedid not.Fix: Add
NeedConversion()+FromInternal()toLongTypesoRow.Convert()coerces the unpickled value to match the schema type. This follows the same pattern already used byTimestampType.Changes:
SimpleTypes.cs: AddedNeedConversion()andFromInternal()toLongType(avoids re-boxing by returningobjdirectly when already a boxed long)Row.cs: Removed the TODO comments that described this issue (now fixed)RowTests.cs: AddedRowGetAsLongFromPickledIntTestthat reproduces the exact scenario from Row unpickles long value incorrectly. #27, plusAssert.Sametest for already boxed longNote:
GetAsalready supports this conversion on main viaTypeConverter; the added behavior is normalization of rawGet()/Valuesand nested collections (ArrayType/MapType with LongType).