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 d9684b2544 Publish built docs triggered by 
9f725d9c7064813cda0de0f87d115354b68d76e6
d9684b2544 is described below

commit d9684b25449e5cbf5023cd0a1aed041e51ed447e
Author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Nov 27 08:29:57 2025 +0000

    Publish built docs triggered by 9f725d9c7064813cda0de0f87d115354b68d76e6
---
 _sources/library-user-guide/upgrading.md.txt | 115 +++++++++++++++++++++++++++
 library-user-guide/upgrading.html            |  99 +++++++++++++++++++++++
 searchindex.js                               |   2 +-
 3 files changed, 215 insertions(+), 1 deletion(-)

diff --git a/_sources/library-user-guide/upgrading.md.txt 
b/_sources/library-user-guide/upgrading.md.txt
index 7a827847dd..25c209c5eb 100644
--- a/_sources/library-user-guide/upgrading.md.txt
+++ b/_sources/library-user-guide/upgrading.md.txt
@@ -202,6 +202,121 @@ Additionally, the FFI structure for Scalar UDF's no 
longer contains a
 `return_type` call. This code was not used since the `ForeignScalarUDF`
 struct implements the `return_field_from_args` instead.
 
+### Projection handling moved from FileScanConfig to FileSource
+
+Projection handling has been moved from `FileScanConfig` into `FileSource` 
implementations. This enables format-specific projection pushdown (e.g., 
Parquet can push down struct field access, Vortex can push down computed 
expressions into un-decoded data).
+
+**Who is affected:**
+
+- Users who have implemented custom `FileSource` implementations
+- Users who use `FileScanConfigBuilder::with_projection_indices` directly
+
+**Breaking changes:**
+
+1. **`FileSource::with_projection` replaced with `try_pushdown_projection`:**
+
+   The `with_projection(&self, config: &FileScanConfig) -> Arc<dyn 
FileSource>` method has been removed and replaced with 
`try_pushdown_projection(&self, projection: &ProjectionExprs) -> 
Result<Option<Arc<dyn FileSource>>>`.
+
+2. **`FileScanConfig.projection_exprs` field removed:**
+
+   Projections are now stored in the `FileSource` directly, not in 
`FileScanConfig`.
+   Various public helper methods that access projection information have been 
removed from `FileScanConfig`.
+
+3. **`FileScanConfigBuilder::with_projection_indices` now returns 
`Result<Self>`:**
+
+   This method can now fail if the projection pushdown fails.
+
+4. **`FileSource::create_file_opener` now returns `Result<Arc<dyn 
FileOpener>>`:**
+
+   Previously returned `Arc<dyn FileOpener>` directly.
+   Any `FileSource` implementation that may fail to create a `FileOpener` 
should now return an appropriate error.
+
+5. **`DataSource::try_swapping_with_projection` signature changed:**
+
+   Parameter changed from `&[ProjectionExpr]` to `&ProjectionExprs`.
+
+**Migration guide:**
+
+If you have a custom `FileSource` implementation:
+
+**Before:**
+
+```rust,ignore
+impl FileSource for MyCustomSource {
+    fn with_projection(&self, config: &FileScanConfig) -> Arc<dyn FileSource> {
+        // Apply projection from config
+        Arc::new(Self { /* ... */ })
+    }
+
+    fn create_file_opener(
+        &self,
+        object_store: Arc<dyn ObjectStore>,
+        base_config: &FileScanConfig,
+        partition: usize,
+    ) -> Arc<dyn FileOpener> {
+        Arc::new(MyOpener { /* ... */ })
+    }
+}
+```
+
+**After:**
+
+```rust,ignore
+impl FileSource for MyCustomSource {
+    fn try_pushdown_projection(
+        &self,
+        projection: &ProjectionExprs,
+    ) -> Result<Option<Arc<dyn FileSource>>> {
+        // Return None if projection cannot be pushed down
+        // Return Some(new_source) with projection applied if it can
+        Ok(Some(Arc::new(Self {
+            projection: Some(projection.clone()),
+            /* ... */
+        })))
+    }
+
+    fn projection(&self) -> Option<&ProjectionExprs> {
+        self.projection.as_ref()
+    }
+
+    fn create_file_opener(
+        &self,
+        object_store: Arc<dyn ObjectStore>,
+        base_config: &FileScanConfig,
+        partition: usize,
+    ) -> Result<Arc<dyn FileOpener>> {
+        Ok(Arc::new(MyOpener { /* ... */ }))
+    }
+}
+```
+
+We recommend you look at 
[#18627](https://github.com/apache/datafusion/pull/18627)
+that introduced these changes for more examples for how this was handled for 
the various built in file sources.
+
+We have added 
[`SplitProjection`](https://docs.rs/datafusion-datasource/latest/datafusion_datasource/projection/struct.SplitProjection.html)
 and 
[`ProjectionOpener`](https://docs.rs/datafusion-datasource/latest/datafusion_datasource/projection/struct.ProjectionOpener.html)
 helpers to make it easier to handle projections in your `FileSource` 
implementations.
+
+For file sources that can only handle simple column selections (not computed 
expressions), use the `SplitProjection` and `ProjectionOpener` helpers to split 
the projection into pushdownable and non-pushdownable parts:
+
+```rust,ignore
+use datafusion_datasource::projection::{SplitProjection, ProjectionOpener};
+
+// In try_pushdown_projection:
+let split = SplitProjection::new(projection, self.table_schema())?;
+// Use split.file_projection() for what to push down to the file format
+// The ProjectionOpener wrapper will handle the rest
+```
+
+**For `FileScanConfigBuilder` users:**
+
+```diff
+let config = FileScanConfigBuilder::new(url, source)
+-   .with_projection_indices(Some(vec![0, 2, 3]))
++   .with_projection_indices(Some(vec![0, 2, 3]))?
+    .build();
+```
+
+**Handling projections in `FileSource`:**
+
 ## DataFusion `51.0.0`
 
 ### `arrow` / `parquet` updated to 57.0.0
diff --git a/library-user-guide/upgrading.html 
b/library-user-guide/upgrading.html
index 08b80c27d8..0d81f1bde4 100644
--- a/library-user-guide/upgrading.html
+++ b/library-user-guide/upgrading.html
@@ -557,6 +557,104 @@ Aggregate and window functions follow the same 
pattern.</p>
 <code class="docutils literal notranslate"><span 
class="pre">return_type</span></code> call. This code was not used since the 
<code class="docutils literal notranslate"><span 
class="pre">ForeignScalarUDF</span></code>
 struct implements the <code class="docutils literal notranslate"><span 
class="pre">return_field_from_args</span></code> instead.</p>
 </section>
+<section id="projection-handling-moved-from-filescanconfig-to-filesource">
+<h3>Projection handling moved from FileScanConfig to FileSource<a 
class="headerlink" 
href="#projection-handling-moved-from-filescanconfig-to-filesource" title="Link 
to this heading">#</a></h3>
+<p>Projection handling has been moved from <code class="docutils literal 
notranslate"><span class="pre">FileScanConfig</span></code> into <code 
class="docutils literal notranslate"><span class="pre">FileSource</span></code> 
implementations. This enables format-specific projection pushdown (e.g., 
Parquet can push down struct field access, Vortex can push down computed 
expressions into un-decoded data).</p>
+<p><strong>Who is affected:</strong></p>
+<ul class="simple">
+<li><p>Users who have implemented custom <code class="docutils literal 
notranslate"><span class="pre">FileSource</span></code> implementations</p></li>
+<li><p>Users who use <code class="docutils literal notranslate"><span 
class="pre">FileScanConfigBuilder::with_projection_indices</span></code> 
directly</p></li>
+</ul>
+<p><strong>Breaking changes:</strong></p>
+<ol class="arabic">
+<li><p><strong><code class="docutils literal notranslate"><span 
class="pre">FileSource::with_projection</span></code> replaced with <code 
class="docutils literal notranslate"><span 
class="pre">try_pushdown_projection</span></code>:</strong></p>
+<p>The <code class="docutils literal notranslate"><span 
class="pre">with_projection(&amp;self,</span> <span class="pre">config:</span> 
<span class="pre">&amp;FileScanConfig)</span> <span class="pre">-&gt;</span> 
<span class="pre">Arc&lt;dyn</span> <span 
class="pre">FileSource&gt;</span></code> method has been removed and replaced 
with <code class="docutils literal notranslate"><span 
class="pre">try_pushdown_projection(&amp;self,</span> <span 
class="pre">projection:</span> <span class="pr [...]
+</li>
+<li><p><strong><code class="docutils literal notranslate"><span 
class="pre">FileScanConfig.projection_exprs</span></code> field 
removed:</strong></p>
+<p>Projections are now stored in the <code class="docutils literal 
notranslate"><span class="pre">FileSource</span></code> directly, not in <code 
class="docutils literal notranslate"><span 
class="pre">FileScanConfig</span></code>.
+Various public helper methods that access projection information have been 
removed from <code class="docutils literal notranslate"><span 
class="pre">FileScanConfig</span></code>.</p>
+</li>
+<li><p><strong><code class="docutils literal notranslate"><span 
class="pre">FileScanConfigBuilder::with_projection_indices</span></code> now 
returns <code class="docutils literal notranslate"><span 
class="pre">Result&lt;Self&gt;</span></code>:</strong></p>
+<p>This method can now fail if the projection pushdown fails.</p>
+</li>
+<li><p><strong><code class="docutils literal notranslate"><span 
class="pre">FileSource::create_file_opener</span></code> now returns <code 
class="docutils literal notranslate"><span 
class="pre">Result&lt;Arc&lt;dyn</span> <span 
class="pre">FileOpener&gt;&gt;</span></code>:</strong></p>
+<p>Previously returned <code class="docutils literal notranslate"><span 
class="pre">Arc&lt;dyn</span> <span class="pre">FileOpener&gt;</span></code> 
directly.
+Any <code class="docutils literal notranslate"><span 
class="pre">FileSource</span></code> implementation that may fail to create a 
<code class="docutils literal notranslate"><span 
class="pre">FileOpener</span></code> should now return an appropriate error.</p>
+</li>
+<li><p><strong><code class="docutils literal notranslate"><span 
class="pre">DataSource::try_swapping_with_projection</span></code> signature 
changed:</strong></p>
+<p>Parameter changed from <code class="docutils literal notranslate"><span 
class="pre">&amp;[ProjectionExpr]</span></code> to <code class="docutils 
literal notranslate"><span class="pre">&amp;ProjectionExprs</span></code>.</p>
+</li>
+</ol>
+<p><strong>Migration guide:</strong></p>
+<p>If you have a custom <code class="docutils literal notranslate"><span 
class="pre">FileSource</span></code> implementation:</p>
+<p><strong>Before:</strong></p>
+<div class="highlight-rust notranslate"><div 
class="highlight"><pre><span></span><span class="k">impl</span><span class="w"> 
</span><span class="n">FileSource</span><span class="w"> </span><span 
class="k">for</span><span class="w"> </span><span 
class="n">MyCustomSource</span><span class="w"> </span><span class="p">{</span>
+<span class="w">    </span><span class="k">fn</span><span class="w"> 
</span><span class="nf">with_projection</span><span class="p">(</span><span 
class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span 
class="w"> </span><span class="n">config</span><span class="p">:</span><span 
class="w"> </span><span class="kp">&amp;</span><span 
class="nc">FileScanConfig</span><span class="p">)</span><span class="w"> 
</span><span class="p">-&gt;</span><span class="w"> </span><span [...]
+<span class="w">        </span><span class="c1">// Apply projection from 
config</span>
+<span class="w">        </span><span class="n">Arc</span><span 
class="p">::</span><span class="n">new</span><span class="p">(</span><span 
class="bp">Self</span><span class="w"> </span><span class="p">{</span><span 
class="w"> </span><span class="cm">/* ... */</span><span class="w"> 
</span><span class="p">})</span>
+<span class="w">    </span><span class="p">}</span>
+
+<span class="w">    </span><span class="k">fn</span><span class="w"> 
</span><span class="nf">create_file_opener</span><span class="p">(</span>
+<span class="w">        </span><span class="o">&amp;</span><span 
class="bp">self</span><span class="p">,</span>
+<span class="w">        </span><span class="n">object_store</span><span 
class="p">:</span><span class="w"> </span><span class="nc">Arc</span><span 
class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span 
class="n">ObjectStore</span><span class="o">&gt;</span><span class="p">,</span>
+<span class="w">        </span><span class="n">base_config</span><span 
class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span 
class="nc">FileScanConfig</span><span class="p">,</span>
+<span class="w">        </span><span class="n">partition</span><span 
class="p">:</span><span class="w"> </span><span class="kt">usize</span><span 
class="p">,</span>
+<span class="w">    </span><span class="p">)</span><span class="w"> 
</span><span class="p">-&gt;</span><span class="w"> </span><span 
class="nc">Arc</span><span class="o">&lt;</span><span class="k">dyn</span><span 
class="w"> </span><span class="n">FileOpener</span><span 
class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
+<span class="w">        </span><span class="n">Arc</span><span 
class="p">::</span><span class="n">new</span><span class="p">(</span><span 
class="n">MyOpener</span><span class="w"> </span><span class="p">{</span><span 
class="w"> </span><span class="cm">/* ... */</span><span class="w"> 
</span><span class="p">})</span>
+<span class="w">    </span><span class="p">}</span>
+<span class="p">}</span>
+</pre></div>
+</div>
+<p><strong>After:</strong></p>
+<div class="highlight-rust notranslate"><div 
class="highlight"><pre><span></span><span class="k">impl</span><span class="w"> 
</span><span class="n">FileSource</span><span class="w"> </span><span 
class="k">for</span><span class="w"> </span><span 
class="n">MyCustomSource</span><span class="w"> </span><span class="p">{</span>
+<span class="w">    </span><span class="k">fn</span><span class="w"> 
</span><span class="nf">try_pushdown_projection</span><span class="p">(</span>
+<span class="w">        </span><span class="o">&amp;</span><span 
class="bp">self</span><span class="p">,</span>
+<span class="w">        </span><span class="n">projection</span><span 
class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span 
class="nc">ProjectionExprs</span><span class="p">,</span>
+<span class="w">    </span><span class="p">)</span><span class="w"> 
</span><span class="p">-&gt;</span><span class="w"> </span><span 
class="nb">Result</span><span class="o">&lt;</span><span 
class="nb">Option</span><span class="o">&lt;</span><span 
class="n">Arc</span><span class="o">&lt;</span><span class="k">dyn</span><span 
class="w"> </span><span class="n">FileSource</span><span 
class="o">&gt;&gt;&gt;</span><span class="w"> </span><span class="p">{</span>
+<span class="w">        </span><span class="c1">// Return None if projection 
cannot be pushed down</span>
+<span class="w">        </span><span class="c1">// Return Some(new_source) 
with projection applied if it can</span>
+<span class="w">        </span><span class="nb">Ok</span><span 
class="p">(</span><span class="nb">Some</span><span class="p">(</span><span 
class="n">Arc</span><span class="p">::</span><span class="n">new</span><span 
class="p">(</span><span class="bp">Self</span><span class="w"> </span><span 
class="p">{</span>
+<span class="w">            </span><span class="n">projection</span><span 
class="p">:</span><span class="w"> </span><span class="nb">Some</span><span 
class="p">(</span><span class="n">projection</span><span 
class="p">.</span><span class="n">clone</span><span class="p">()),</span>
+<span class="w">            </span><span class="cm">/* ... */</span>
+<span class="w">        </span><span class="p">})))</span>
+<span class="w">    </span><span class="p">}</span>
+
+<span class="w">    </span><span class="k">fn</span><span class="w"> 
</span><span class="nf">projection</span><span class="p">(</span><span 
class="o">&amp;</span><span class="bp">self</span><span class="p">)</span><span 
class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span 
class="nb">Option</span><span class="o">&lt;&amp;</span><span 
class="n">ProjectionExprs</span><span class="o">&gt;</span><span class="w"> 
</span><span class="p">{</span>
+<span class="w">        </span><span class="bp">self</span><span 
class="p">.</span><span class="n">projection</span><span 
class="p">.</span><span class="n">as_ref</span><span class="p">()</span>
+<span class="w">    </span><span class="p">}</span>
+
+<span class="w">    </span><span class="k">fn</span><span class="w"> 
</span><span class="nf">create_file_opener</span><span class="p">(</span>
+<span class="w">        </span><span class="o">&amp;</span><span 
class="bp">self</span><span class="p">,</span>
+<span class="w">        </span><span class="n">object_store</span><span 
class="p">:</span><span class="w"> </span><span class="nc">Arc</span><span 
class="o">&lt;</span><span class="k">dyn</span><span class="w"> </span><span 
class="n">ObjectStore</span><span class="o">&gt;</span><span class="p">,</span>
+<span class="w">        </span><span class="n">base_config</span><span 
class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span 
class="nc">FileScanConfig</span><span class="p">,</span>
+<span class="w">        </span><span class="n">partition</span><span 
class="p">:</span><span class="w"> </span><span class="kt">usize</span><span 
class="p">,</span>
+<span class="w">    </span><span class="p">)</span><span class="w"> 
</span><span class="p">-&gt;</span><span class="w"> </span><span 
class="nb">Result</span><span class="o">&lt;</span><span 
class="n">Arc</span><span class="o">&lt;</span><span class="k">dyn</span><span 
class="w"> </span><span class="n">FileOpener</span><span 
class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span>
+<span class="w">        </span><span class="nb">Ok</span><span 
class="p">(</span><span class="n">Arc</span><span class="p">::</span><span 
class="n">new</span><span class="p">(</span><span 
class="n">MyOpener</span><span class="w"> </span><span class="p">{</span><span 
class="w"> </span><span class="cm">/* ... */</span><span class="w"> 
</span><span class="p">}))</span>
+<span class="w">    </span><span class="p">}</span>
+<span class="p">}</span>
+</pre></div>
+</div>
+<p>We recommend you look at <a class="reference external" 
href="https://github.com/apache/datafusion/pull/18627";>#18627</a>
+that introduced these changes for more examples for how this was handled for 
the various built in file sources.</p>
+<p>We have added <a class="reference external" 
href="https://docs.rs/datafusion-datasource/latest/datafusion_datasource/projection/struct.SplitProjection.html";><code
 class="docutils literal notranslate"><span 
class="pre">SplitProjection</span></code></a> and <a class="reference external" 
href="https://docs.rs/datafusion-datasource/latest/datafusion_datasource/projection/struct.ProjectionOpener.html";><code
 class="docutils literal notranslate"><span 
class="pre">ProjectionOpener</span></cod [...]
+<p>For file sources that can only handle simple column selections (not 
computed expressions), use the <code class="docutils literal notranslate"><span 
class="pre">SplitProjection</span></code> and <code class="docutils literal 
notranslate"><span class="pre">ProjectionOpener</span></code> helpers to split 
the projection into pushdownable and non-pushdownable parts:</p>
+<div class="highlight-rust notranslate"><div 
class="highlight"><pre><span></span><span class="k">use</span><span class="w"> 
</span><span class="n">datafusion_datasource</span><span 
class="p">::</span><span class="n">projection</span><span 
class="p">::{</span><span class="n">SplitProjection</span><span 
class="p">,</span><span class="w"> </span><span 
class="n">ProjectionOpener</span><span class="p">};</span>
+
+<span class="c1">// In try_pushdown_projection:</span>
+<span class="kd">let</span><span class="w"> </span><span 
class="n">split</span><span class="w"> </span><span class="o">=</span><span 
class="w"> </span><span class="n">SplitProjection</span><span 
class="p">::</span><span class="n">new</span><span class="p">(</span><span 
class="n">projection</span><span class="p">,</span><span class="w"> 
</span><span class="bp">self</span><span class="p">.</span><span 
class="n">table_schema</span><span class="p">())</span><span 
class="o">?</span><span clas [...]
+<span class="c1">// Use split.file_projection() for what to push down to the 
file format</span>
+<span class="c1">// The ProjectionOpener wrapper will handle the rest</span>
+</pre></div>
+</div>
+<p><strong>For <code class="docutils literal notranslate"><span 
class="pre">FileScanConfigBuilder</span></code> users:</strong></p>
+<div class="highlight-diff notranslate"><div 
class="highlight"><pre><span></span>let config = 
FileScanConfigBuilder::new(url, source)
+<span class="gd">-   .with_projection_indices(Some(vec![0, 2, 3]))</span>
+<span class="gi">+   .with_projection_indices(Some(vec![0, 2, 3]))?</span>
+<span class="w"> </span>   .build();
+</pre></div>
+</div>
+<p><strong>Handling projections in <code class="docutils literal 
notranslate"><span class="pre">FileSource</span></code>:</strong></p>
+</section>
 </section>
 <section id="datafusion-51-0-0">
 <h2>DataFusion <code class="docutils literal notranslate"><span 
class="pre">51.0.0</span></code><a class="headerlink" href="#datafusion-51-0-0" 
title="Link to this heading">#</a></h2>
@@ -1801,6 +1899,7 @@ take care of constructing the <code class="docutils 
literal notranslate"><span c
 <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#aggregateudfimpl-supports-null-handling-clause-now-defaults-to-false"><code
 class="docutils literal notranslate"><span 
class="pre">AggregateUDFImpl::supports_null_handling_clause</span></code> now 
defaults to <code class="docutils literal notranslate"><span 
class="pre">false</span></code></a></li>
 <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#api-change-for-cacheaccessor-trait">API change for <code class="docutils 
literal notranslate"><span class="pre">CacheAccessor</span></code> 
trait</a></li>
 <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#ffi-crate-updates">FFI crate updates</a></li>
+<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#projection-handling-moved-from-filescanconfig-to-filesource">Projection 
handling moved from FileScanConfig to FileSource</a></li>
 </ul>
 </li>
 <li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" 
href="#datafusion-51-0-0">DataFusion <code class="docutils literal 
notranslate"><span class="pre">51.0.0</span></code></a><ul class="nav 
section-nav flex-column">
diff --git a/searchindex.js b/searchindex.js
index 7ee1f97602..fed564391c 100644
--- a/searchindex.js
+++ b/searchindex.js
@@ -1 +1 @@
-Search.setIndex({"alltitles":{"!=":[[60,"op-neq"]],"!~":[[60,"op-re-not-match"]],"!~*":[[60,"op-re-not-match-i"]],"!~~":[[60,"id19"]],"!~~*":[[60,"id20"]],"#":[[60,"op-bit-xor"]],"%":[[60,"op-modulo"]],"&":[[60,"op-bit-and"]],"(relation,
 name) tuples in logical fields and logical columns are 
unique":[[13,"relation-name-tuples-in-logical-fields-and-logical-columns-are-unique"]],"*":[[60,"op-multiply"]],"+":[[60,"op-plus"]],"-":[[60,"op-minus"]],"/":[[60,"op-divide"]],"<":[[60,"op-lt"]],"<
 [...]
\ No newline at end of file
+Search.setIndex({"alltitles":{"!=":[[60,"op-neq"]],"!~":[[60,"op-re-not-match"]],"!~*":[[60,"op-re-not-match-i"]],"!~~":[[60,"id19"]],"!~~*":[[60,"id20"]],"#":[[60,"op-bit-xor"]],"%":[[60,"op-modulo"]],"&":[[60,"op-bit-and"]],"(relation,
 name) tuples in logical fields and logical columns are 
unique":[[13,"relation-name-tuples-in-logical-fields-and-logical-columns-are-unique"]],"*":[[60,"op-multiply"]],"+":[[60,"op-plus"]],"-":[[60,"op-minus"]],"/":[[60,"op-divide"]],"<":[[60,"op-lt"]],"<
 [...]
\ No newline at end of file


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

Reply via email to