CurtHagenlocher commented on code in PR #445:
URL: https://github.com/apache/arrow-dotnet/pull/445#discussion_r4113950332


##########
src/Apache.Arrow.Operations/Shredding/ShredSchemaInferer.cs:
##########
@@ -53,6 +53,28 @@ public ShredSchema Infer(IEnumerable<VariantValue> values, 
ShredOptions options
             return BuildSchema(stats, totalCount, options, 0);
         }
 
+        /// <summary>
+        /// Infers a shredding schema by analyzing the given nullable values.
+        /// <c>null</c> entries are SQL-NULL rows and are ignored; they carry 
no type
+        /// information and do not count toward frequency thresholds.
+        /// </summary>
+        /// <param name="values">The variant values to analyze.</param>
+        /// <param name="options">Options controlling depth, frequency, and 
type consistency thresholds.</param>
+        /// <returns>An inferred <see cref="ShredSchema"/>.</returns>
+        public ShredSchema Infer(IEnumerable<VariantValue?> values, 
ShredOptions options = null)

Review Comment:
   Keeping the overload. The only calls that become ambiguous are an untyped 
`null` or `default` literal for `values`, and those calls could only ever throw 
`ArgumentNullException`, so nothing that does useful work is affected. A null 
in a typed variable, arrays and collection expressions (including `[v, null]`) 
all still resolve correctly, and already-compiled callers stay bound to the 
original method. `VariantArray.Builder.AppendRange` already uses the same 
`VariantValue` / `VariantValue?` overload pair, so a separate name would be 
less consistent with the rest of the library. I've updated the PR description 
to explain this.



##########
src/Apache.Arrow.Operations/Shredding/VariantShredder.cs:
##########
@@ -66,6 +66,39 @@ public static (byte[] Metadata, IReadOnlyList<ShredResult> 
Rows) Shred(
             return (metadataBytes, results);
         }
 
+        /// <summary>
+        /// Shreds a column of nullable variant values. A <c>null</c> entry is 
a
+        /// SQL-NULL row, as opposed to <see cref="VariantValue.Null"/>, which 
is a
+        /// present variant null. SQL-NULL rows produce a <c>null</c> entry in 
the
+        /// returned rows, which <see 
cref="ShreddedVariantArrayBuilder.Build"/> turns
+        /// into a null element of the resulting array.
+        /// </summary>
+        public static (byte[] Metadata, IReadOnlyList<ShredResult> Rows) Shred(
+            IEnumerable<VariantValue?> values,
+            ShredSchema schema)

Review Comment:
   Keeping the overload. The only calls that become ambiguous are an untyped 
`null` or `default` literal for `values`, and those calls could only ever throw 
`ArgumentNullException`, so nothing that does useful work is affected. A null 
in a typed variable, arrays and collection expressions (including `[v, null]`) 
all still resolve correctly, and already-compiled callers stay bound to the 
original method. `VariantArray.Builder.AppendRange` already uses the same 
`VariantValue` / `VariantValue?` overload pair, so a separate name would be 
less consistent with the rest of the library. I've updated the PR description 
to explain this.



##########
src/Apache.Arrow.Operations/Shredding/VariantShredder.cs:
##########
@@ -66,6 +66,39 @@ public static (byte[] Metadata, IReadOnlyList<ShredResult> 
Rows) Shred(
             return (metadataBytes, results);
         }
 
+        /// <summary>
+        /// Shreds a column of nullable variant values. A <c>null</c> entry is 
a
+        /// SQL-NULL row, as opposed to <see cref="VariantValue.Null"/>, which 
is a
+        /// present variant null. SQL-NULL rows produce a <c>null</c> entry in 
the
+        /// returned rows, which <see 
cref="ShreddedVariantArrayBuilder.Build"/> turns
+        /// into a null element of the resulting array.
+        /// </summary>
+        public static (byte[] Metadata, IReadOnlyList<ShredResult> Rows) Shred(
+            IEnumerable<VariantValue?> values,
+            ShredSchema schema)
+        {
+            if (values == null) throw new 
ArgumentNullException(nameof(values));
+            if (schema == null) throw new 
ArgumentNullException(nameof(schema));
+
+            List<VariantValue?> rows = values as List<VariantValue?> ?? new 
List<VariantValue?>(values);
+
+            VariantMetadataBuilder metadata = new VariantMetadataBuilder();
+            foreach (VariantValue? row in rows)
+            {
+                if (row.HasValue) CollectFieldNames(row.Value, metadata);
+            }
+            byte[] metadataBytes = metadata.Build(out int[] idRemap);
+
+            ShredResult[] results = new ShredResult[rows.Count];
+            for (int i = 0; i < rows.Count; i++)
+            {
+                VariantValue? row = rows[i];
+                results[i] = row.HasValue ? Shred(row.Value, schema, metadata, 
idRemap) : null;

Review Comment:
   Good catch, fixed in 9155656. `Reconstruct` now returns `null` for a `null` 
result instead of throwing. That matches its existing contract, where `null` 
already means "no value". A top-level row can't legitimately be missing, so at 
the top level `null` can only mean a SQL-NULL row. Added 
`Reconstruct_RoundTripsNullRows`, which shreds rows containing both a SQL-NULL 
row and a present `VariantValue.Null` and checks that each reconstructs 
correctly.



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