This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new 15bf3a358d Publish built docs triggered by 
8c478e945274086edf13ea3cab89670b6368938f
15bf3a358d is described below

commit 15bf3a358d4fa5d07b5a01cdf29a4ed7e3083289
Author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Feb 3 02:23:55 2026 +0000

    Publish built docs triggered by 8c478e945274086edf13ea3cab89670b6368938f
---
 _sources/library-user-guide/upgrading.md.txt | 91 ++++++++++++++++++++++++++++
 library-user-guide/upgrading.html            | 71 ++++++++++++++++++++++
 searchindex.js                               |  2 +-
 3 files changed, 163 insertions(+), 1 deletion(-)

diff --git a/_sources/library-user-guide/upgrading.md.txt 
b/_sources/library-user-guide/upgrading.md.txt
index f5c4fc0921..182f2f0ef9 100644
--- a/_sources/library-user-guide/upgrading.md.txt
+++ b/_sources/library-user-guide/upgrading.md.txt
@@ -156,6 +156,97 @@ let context = SimplifyContext::default()
 
 See [`SimplifyContext` 
documentation](https://docs.rs/datafusion-expr/latest/datafusion_expr/simplify/struct.SimplifyContext.html)
 for more details.
 
+### Struct Casting Now Requires Field Name Overlap
+
+DataFusion's struct casting mechanism previously allowed casting between 
structs with differing field names if the field counts matched. This 
"positional fallback" behavior could silently misalign fields and cause data 
corruption.
+
+**Breaking Change:**
+
+Starting with DataFusion 53.0.0, struct casts now require **at least one 
overlapping field name** between the source and target structs. Casts without 
field name overlap are rejected at plan time with a clear error message.
+
+**Who is affected:**
+
+- Applications that cast between structs with no overlapping field names
+- Queries that rely on positional struct field mapping (e.g., casting 
`struct(x, y)` to `struct(a, b)` based solely on position)
+- Code that constructs or transforms struct columns programmatically
+
+**Migration guide:**
+
+If you encounter an error like:
+
+```text
+Cannot cast struct with 2 fields to 2 fields because there is no field name 
overlap
+```
+
+You must explicitly rename or map fields to ensure at least one field name 
matches. Here are common patterns:
+
+**Example 1: Source and target field names already match (Name-based casting)**
+
+**Success case (field names align):**
+
+```sql
+-- source_col has schema: STRUCT<x INT, y INT>
+-- Casting to the same field names succeeds (no-op or type validation only)
+SELECT CAST(source_col AS STRUCT<x INT, y INT>) FROM table1;
+```
+
+**Example 2: Source and target field names differ (Migration scenario)**
+
+**What fails now (no field name overlap):**
+
+```sql
+-- source_col has schema: STRUCT<a INT, b INT>
+-- This FAILS because there is no field name overlap:
+-- ❌ SELECT CAST(source_col AS STRUCT<x INT, y INT>) FROM table1;
+-- Error: Cannot cast struct with 2 fields to 2 fields because there is no 
field name overlap
+```
+
+**Migration options (must align names):**
+
+**Option A: Use struct constructor for explicit field mapping**
+
+```sql
+-- source_col has schema: STRUCT<a INT, b INT>
+-- Use STRUCT_CONSTRUCT with explicit field names
+SELECT STRUCT_CONSTRUCT(
+    'x', source_col.a,
+    'y', source_col.b
+) AS renamed_struct FROM table1;
+```
+
+**Option B: Rename in the cast target to match source names**
+
+```sql
+-- source_col has schema: STRUCT<a INT, b INT>
+-- Cast to target with matching field names
+SELECT CAST(source_col AS STRUCT<a INT, b INT>) FROM table1;
+```
+
+**Example 3: Using struct constructors in Rust API**
+
+If you need to map fields programmatically, build the target struct explicitly:
+
+```rust,ignore
+// Build the target struct with explicit field names
+let target_struct_type = DataType::Struct(vec![
+    FieldRef::new("x", DataType::Int32),
+    FieldRef::new("y", DataType::Utf8),
+]);
+
+// Use struct constructors rather than casting for field mapping
+// This makes the field mapping explicit and unambiguous
+// Use struct builders or row constructors that preserve your mapping logic
+```
+
+**Why this change:**
+
+1. **Safety:** Field names are now the primary contract for struct 
compatibility
+2. **Explicitness:** Prevents silent data misalignment caused by positional 
assumptions
+3. **Consistency:** Matches DuckDB's behavior and aligns with other SQL 
engines that enforce name-based matching
+4. **Debuggability:** Errors now appear at plan time rather than as silent 
data corruption
+
+See [Issue #19841](https://github.com/apache/datafusion/issues/19841) and [PR 
#19955](https://github.com/apache/datafusion/pull/19955) for more details.
+
 ### `FilterExec` builder methods deprecated
 
 The following methods on `FilterExec` have been deprecated in favor of using 
`FilterExecBuilder`:
diff --git a/library-user-guide/upgrading.html 
b/library-user-guide/upgrading.html
index 13dc0af168..e79e507df1 100644
--- a/library-user-guide/upgrading.html
+++ b/library-user-guide/upgrading.html
@@ -519,6 +519,76 @@ literals must initialize this field.</p>
 </div>
 <p>See <a class="reference external" 
href="https://docs.rs/datafusion-expr/latest/datafusion_expr/simplify/struct.SimplifyContext.html";><code
 class="docutils literal notranslate"><span 
class="pre">SimplifyContext</span></code> documentation</a> for more 
details.</p>
 </section>
+<section id="struct-casting-now-requires-field-name-overlap">
+<h3>Struct Casting Now Requires Field Name Overlap<a class="headerlink" 
href="#struct-casting-now-requires-field-name-overlap" title="Link to this 
heading">#</a></h3>
+<p>DataFusion’s struct casting mechanism previously allowed casting between 
structs with differing field names if the field counts matched. This 
“positional fallback” behavior could silently misalign fields and cause data 
corruption.</p>
+<p><strong>Breaking Change:</strong></p>
+<p>Starting with DataFusion 53.0.0, struct casts now require <strong>at least 
one overlapping field name</strong> between the source and target structs. 
Casts without field name overlap are rejected at plan time with a clear error 
message.</p>
+<p><strong>Who is affected:</strong></p>
+<ul class="simple">
+<li><p>Applications that cast between structs with no overlapping field 
names</p></li>
+<li><p>Queries that rely on positional struct field mapping (e.g., casting 
<code class="docutils literal notranslate"><span class="pre">struct(x,</span> 
<span class="pre">y)</span></code> to <code class="docutils literal 
notranslate"><span class="pre">struct(a,</span> <span 
class="pre">b)</span></code> based solely on position)</p></li>
+<li><p>Code that constructs or transforms struct columns 
programmatically</p></li>
+</ul>
+<p><strong>Migration guide:</strong></p>
+<p>If you encounter an error like:</p>
+<div class="highlight-text notranslate"><div 
class="highlight"><pre><span></span>Cannot cast struct with 2 fields to 2 
fields because there is no field name overlap
+</pre></div>
+</div>
+<p>You must explicitly rename or map fields to ensure at least one field name 
matches. Here are common patterns:</p>
+<p><strong>Example 1: Source and target field names already match (Name-based 
casting)</strong></p>
+<p><strong>Success case (field names align):</strong></p>
+<div class="highlight-sql notranslate"><div 
class="highlight"><pre><span></span><span class="c1">-- source_col has schema: 
STRUCT&lt;x INT, y INT&gt;</span>
+<span class="c1">-- Casting to the same field names succeeds (no-op or type 
validation only)</span>
+<span class="k">SELECT</span><span class="w"> </span><span 
class="k">CAST</span><span class="p">(</span><span 
class="n">source_col</span><span class="w"> </span><span 
class="k">AS</span><span class="w"> </span><span class="n">STRUCT</span><span 
class="o">&lt;</span><span class="n">x</span><span class="w"> </span><span 
class="nb">INT</span><span class="p">,</span><span class="w"> </span><span 
class="n">y</span><span class="w"> </span><span class="nb">INT</span><span 
class="o">&gt;</span>< [...]
+</pre></div>
+</div>
+<p><strong>Example 2: Source and target field names differ (Migration 
scenario)</strong></p>
+<p><strong>What fails now (no field name overlap):</strong></p>
+<div class="highlight-sql notranslate"><div 
class="highlight"><pre><span></span><span class="c1">-- source_col has schema: 
STRUCT&lt;a INT, b INT&gt;</span>
+<span class="c1">-- This FAILS because there is no field name overlap:</span>
+<span class="c1">-- ❌ SELECT CAST(source_col AS STRUCT&lt;x INT, y INT&gt;) 
FROM table1;</span>
+<span class="c1">-- Error: Cannot cast struct with 2 fields to 2 fields 
because there is no field name overlap</span>
+</pre></div>
+</div>
+<p><strong>Migration options (must align names):</strong></p>
+<p><strong>Option A: Use struct constructor for explicit field 
mapping</strong></p>
+<div class="highlight-sql notranslate"><div 
class="highlight"><pre><span></span><span class="c1">-- source_col has schema: 
STRUCT&lt;a INT, b INT&gt;</span>
+<span class="c1">-- Use STRUCT_CONSTRUCT with explicit field names</span>
+<span class="k">SELECT</span><span class="w"> </span><span 
class="n">STRUCT_CONSTRUCT</span><span class="p">(</span>
+<span class="w">    </span><span class="s1">&#39;x&#39;</span><span 
class="p">,</span><span class="w"> </span><span 
class="n">source_col</span><span class="p">.</span><span 
class="n">a</span><span class="p">,</span>
+<span class="w">    </span><span class="s1">&#39;y&#39;</span><span 
class="p">,</span><span class="w"> </span><span 
class="n">source_col</span><span class="p">.</span><span class="n">b</span>
+<span class="p">)</span><span class="w"> </span><span class="k">AS</span><span 
class="w"> </span><span class="n">renamed_struct</span><span class="w"> 
</span><span class="k">FROM</span><span class="w"> </span><span 
class="n">table1</span><span class="p">;</span>
+</pre></div>
+</div>
+<p><strong>Option B: Rename in the cast target to match source 
names</strong></p>
+<div class="highlight-sql notranslate"><div 
class="highlight"><pre><span></span><span class="c1">-- source_col has schema: 
STRUCT&lt;a INT, b INT&gt;</span>
+<span class="c1">-- Cast to target with matching field names</span>
+<span class="k">SELECT</span><span class="w"> </span><span 
class="k">CAST</span><span class="p">(</span><span 
class="n">source_col</span><span class="w"> </span><span 
class="k">AS</span><span class="w"> </span><span class="n">STRUCT</span><span 
class="o">&lt;</span><span class="n">a</span><span class="w"> </span><span 
class="nb">INT</span><span class="p">,</span><span class="w"> </span><span 
class="n">b</span><span class="w"> </span><span class="nb">INT</span><span 
class="o">&gt;</span>< [...]
+</pre></div>
+</div>
+<p><strong>Example 3: Using struct constructors in Rust API</strong></p>
+<p>If you need to map fields programmatically, build the target struct 
explicitly:</p>
+<div class="highlight-rust notranslate"><div 
class="highlight"><pre><span></span><span class="c1">// Build the target struct 
with explicit field names</span>
+<span class="kd">let</span><span class="w"> </span><span 
class="n">target_struct_type</span><span class="w"> </span><span 
class="o">=</span><span class="w"> </span><span class="n">DataType</span><span 
class="p">::</span><span class="n">Struct</span><span class="p">(</span><span 
class="fm">vec!</span><span class="p">[</span>
+<span class="w">    </span><span class="n">FieldRef</span><span 
class="p">::</span><span class="n">new</span><span class="p">(</span><span 
class="s">&quot;x&quot;</span><span class="p">,</span><span class="w"> 
</span><span class="n">DataType</span><span class="p">::</span><span 
class="n">Int32</span><span class="p">),</span>
+<span class="w">    </span><span class="n">FieldRef</span><span 
class="p">::</span><span class="n">new</span><span class="p">(</span><span 
class="s">&quot;y&quot;</span><span class="p">,</span><span class="w"> 
</span><span class="n">DataType</span><span class="p">::</span><span 
class="n">Utf8</span><span class="p">),</span>
+<span class="p">]);</span>
+
+<span class="c1">// Use struct constructors rather than casting for field 
mapping</span>
+<span class="c1">// This makes the field mapping explicit and 
unambiguous</span>
+<span class="c1">// Use struct builders or row constructors that preserve your 
mapping logic</span>
+</pre></div>
+</div>
+<p><strong>Why this change:</strong></p>
+<ol class="arabic simple">
+<li><p><strong>Safety:</strong> Field names are now the primary contract for 
struct compatibility</p></li>
+<li><p><strong>Explicitness:</strong> Prevents silent data misalignment caused 
by positional assumptions</p></li>
+<li><p><strong>Consistency:</strong> Matches DuckDB’s behavior and aligns with 
other SQL engines that enforce name-based matching</p></li>
+<li><p><strong>Debuggability:</strong> Errors now appear at plan time rather 
than as silent data corruption</p></li>
+</ol>
+<p>See <a class="reference external" 
href="https://github.com/apache/datafusion/issues/19841";>Issue #19841</a> and 
<a class="reference external" 
href="https://github.com/apache/datafusion/pull/19955";>PR #19955</a> for more 
details.</p>
+</section>
 <section id="filterexec-builder-methods-deprecated">
 <h3><code class="docutils literal notranslate"><span 
class="pre">FilterExec</span></code> builder methods deprecated<a 
class="headerlink" href="#filterexec-builder-methods-deprecated" title="Link to 
this heading">#</a></h3>
 <p>The following methods on <code class="docutils literal notranslate"><span 
class="pre">FilterExec</span></code> have been deprecated in favor of using 
<code class="docutils literal notranslate"><span 
class="pre">FilterExecBuilder</span></code>:</p>
@@ -2339,6 +2409,7 @@ take care of constructing the <code class="docutils 
literal notranslate"><span c
 <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" 
href="#datafusion-53-0-0">DataFusion <code class="docutils literal 
notranslate"><span class="pre">53.0.0</span></code></a><ul class="nav 
section-nav flex-column">
 <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#filesinkconfig-adds-file-output-mode"><code class="docutils literal 
notranslate"><span class="pre">FileSinkConfig</span></code> adds <code 
class="docutils literal notranslate"><span 
class="pre">file_output_mode</span></code></a></li>
 <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#simplifyinfo-trait-removed-simplifycontext-now-uses-builder-style-api"><code
 class="docutils literal notranslate"><span 
class="pre">SimplifyInfo</span></code> trait removed, <code class="docutils 
literal notranslate"><span class="pre">SimplifyContext</span></code> now uses 
builder-style API</a></li>
+<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#struct-casting-now-requires-field-name-overlap">Struct Casting Now 
Requires Field Name Overlap</a></li>
 <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#filterexec-builder-methods-deprecated"><code class="docutils literal 
notranslate"><span class="pre">FilterExec</span></code> builder methods 
deprecated</a></li>
 <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#protobuf-conversion-trait-added">Protobuf conversion trait added</a></li>
 <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#generate-series-and-range-table-functions-changed"><code class="docutils 
literal notranslate"><span class="pre">generate_series</span></code> and <code 
class="docutils literal notranslate"><span class="pre">range</span></code> 
table functions changed</a></li>
diff --git a/searchindex.js b/searchindex.js
index cea0434dcb..dc74a6873b 100644
--- a/searchindex.js
+++ b/searchindex.js
@@ -1 +1 @@
-Search.setIndex({"alltitles":{"!=":[[62,"op-neq"]],"!~":[[62,"op-re-not-match"]],"!~*":[[62,"op-re-not-match-i"]],"!~~":[[62,"id19"]],"!~~*":[[62,"id20"]],"#":[[62,"op-bit-xor"]],"%":[[62,"op-modulo"]],"&":[[62,"op-bit-and"]],"(relation,
 name) tuples in logical fields and logical columns are 
unique":[[14,"relation-name-tuples-in-logical-fields-and-logical-columns-are-unique"]],"*":[[62,"op-multiply"]],"+":[[62,"op-plus"]],"-":[[62,"op-minus"]],"/":[[62,"op-divide"]],"1.
 Array Literal Con [...]
\ No newline at end of file
+Search.setIndex({"alltitles":{"!=":[[62,"op-neq"]],"!~":[[62,"op-re-not-match"]],"!~*":[[62,"op-re-not-match-i"]],"!~~":[[62,"id19"]],"!~~*":[[62,"id20"]],"#":[[62,"op-bit-xor"]],"%":[[62,"op-modulo"]],"&":[[62,"op-bit-and"]],"(relation,
 name) tuples in logical fields and logical columns are 
unique":[[14,"relation-name-tuples-in-logical-fields-and-logical-columns-are-unique"]],"*":[[62,"op-multiply"]],"+":[[62,"op-plus"]],"-":[[62,"op-minus"]],"/":[[62,"op-divide"]],"1.
 Array Literal Con [...]
\ No newline at end of file


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

Reply via email to