<h3 dir="auto">Apache Airflow version</h3>
<p dir="auto">2.3.0 (latest released)</p>
<h3 dir="auto">What happened</h3>
<p dir="auto">Soft link and folder under same root folder will be handled as the same relative path. Say i have dags folder which looks like this:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="-dags:
  -- .airflowignore
  -- folder
  -- soft-links-to-folder -&gt; folder"><pre class="notranslate"><code class="notranslate">-dags:
  -- .airflowignore
  -- folder
  -- soft-links-to-folder -&gt; folder
</code></pre></div>
<p dir="auto">and .airflowignore:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="folder/"><pre class="notranslate"><code class="notranslate">folder/
</code></pre></div>
<p dir="auto">both folder and soft-links-to-folder will be ignored.</p>
<h3 dir="auto">What you think should happen instead</h3>
<p dir="auto">Only the folder should be ignored. This is the expected behavior in airflow 2.2.4, before i upgraded. <del>The root cause is that both _RegexpIgnoreRule and _GlobIgnoreRule is calling <code class="notranslate">relative_to</code> method to get search path.</del></p>
<h3 dir="auto">How to reproduce</h3>
<p dir="auto">check <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/tirkarthi/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/tirkarthi">@tirkarthi</a> comment for the test case.</p>
<h3 dir="auto">Operating System</h3>
<p dir="auto">ubuntu</p>
<h3 dir="auto">Versions of Apache Airflow Providers</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Deployment</h3>
<p dir="auto">Official Apache Airflow Helm Chart</p>
<h3 dir="auto">Deployment details</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Anything else</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Are you willing to submit PR?</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Yes I am willing to submit a PR!</li>
</ul>
<h3 dir="auto">Code of Conduct</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I agree to follow this project's <a href="https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md">Code of Conduct</a></li>
</ul>
<h3 dir="auto">Apache Airflow version</h3>
<p dir="auto">main (development)</p>
<h3 dir="auto">What happened</h3>
<p dir="auto">The common sql <code class="notranslate">fetch_all_handler</code> modified by <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1039617992" data-permission-text="Title is private" data-url="https://github.com/apache/airflow/issues/19313" data-hovercard-type="issue" data-hovercard-url="/apache/airflow/issues/19313/hovercard" href="https://github.com/apache/airflow/issues/19313">#19313</a> uses <code class="notranslate">cursor.returns_rows</code> which is not dbapi2 compliant but sqlalchemy specific.</p>
<p dir="auto">The <code class="notranslate">DBApiHook.run</code> method does not use <code class="notranslate">sqlalchemy</code> since it uses <code class="notranslate">get_conn</code> and most (if not all) drivers cursors do not have the <code class="notranslate">returns_rows</code> attribute (ex: <code class="notranslate">pymssql</code> and <code class="notranslate">jaydebeapi</code> do not have it: see below).</p>
<p dir="auto">Why did the tests in <a href="https://github.com/apache/airflow/actions/runs/2712108854">https://github.com/apache/airflow/actions/runs/2712108854</a> passed:</p>
<ul dir="auto">
<li>the jdbc's operator test assert that the run method is called with <code class="notranslate">fetch_all_handler</code> which is not tested.</li>
<li>the databricks's hook test cursor mock has the <code class="notranslate">returns_rows</code> attribute.</li>
<li>in all tests, the mock used will make <code class="notranslate">hasattr(cursor, "returns_rows")</code> resolves to <code class="notranslate">True</code> which is why tests passed</li>
</ul>
<p dir="auto"><code class="notranslate">jaydebeapi</code>'s cursor attributes:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; dir(cur)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_close_last', '_connection', '_converters', '_description', '_meta', '_prep', '_rs', '_set_stmt_parms', 'arraysize', 'close', 'description', 'execute', 'executemany', 'fetchall', 'fetchmany', 'fetchone', 'rowcount', 'setinputsizes', 'setoutputsize']"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-en">dir</span>(<span class="pl-s1">cur</span>)
[<span class="pl-s">'__class__'</span>, <span class="pl-s">'__delattr__'</span>, <span class="pl-s">'__dict__'</span>, <span class="pl-s">'__dir__'</span>, <span class="pl-s">'__doc__'</span>, <span class="pl-s">'__enter__'</span>, <span class="pl-s">'__eq__'</span>, <span class="pl-s">'__exit__'</span>, <span class="pl-s">'__format__'</span>, <span class="pl-s">'__ge__'</span>, <span class="pl-s">'__getattribute__'</span>, <span class="pl-s">'__gt__'</span>, <span class="pl-s">'__hash__'</span>, <span class="pl-s">'__init__'</span>, <span class="pl-s">'__init_subclass__'</span>, <span class="pl-s">'__le__'</span>, <span class="pl-s">'__lt__'</span>, <span class="pl-s">'__module__'</span>, <span class="pl-s">'__ne__'</span>, <span class="pl-s">'__new__'</span>, <span class="pl-s">'__reduce__'</span>, <span class="pl-s">'__reduce_ex__'</span>, <span class="pl-s">'__repr__'</span>, <span class="pl-s">'__setattr__'</span>, <span class="pl-s">'__sizeof__'</span>, <span class="pl-s">'__str__'</span>, <span class="pl-s">'__subclasshook__'</span>, <span class="pl-s">'__weakref__'</span>, <span class="pl-s">'_close_last'</span>, <span class="pl-s">'_connection'</span>, <span class="pl-s">'_converters'</span>, <span class="pl-s">'_description'</span>, <span class="pl-s">'_meta'</span>, <span class="pl-s">'_prep'</span>, <span class="pl-s">'_rs'</span>, <span class="pl-s">'_set_stmt_parms'</span>, <span class="pl-s">'arraysize'</span>, <span class="pl-s">'close'</span>, <span class="pl-s">'description'</span>, <span class="pl-s">'execute'</span>, <span class="pl-s">'executemany'</span>, <span class="pl-s">'fetchall'</span>, <span class="pl-s">'fetchmany'</span>, <span class="pl-s">'fetchone'</span>, <span class="pl-s">'rowcount'</span>, <span class="pl-s">'setinputsizes'</span>, <span class="pl-s">'setoutputsize'</span>]</pre></div>
<p dir="auto"><code class="notranslate">pymssql</code>'s cursor attributes:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; dir(cur)
['__class__', '__delattr__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__pyx_vtable__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '_source', 'callproc', 'close', 'connection', 'description', 'execute', 'executemany', 'fetchall', 'fetchmany', 'fetchone', 'lastrowid', 'nextset', 'returnvalue', 'rowcount', 'rownumber', 'setinputsizes', 'setoutputsize']"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-en">dir</span>(<span class="pl-s1">cur</span>)
[<span class="pl-s">'__class__'</span>, <span class="pl-s">'__delattr__'</span>, <span class="pl-s">'__dir__'</span>, <span class="pl-s">'__doc__'</span>, <span class="pl-s">'__enter__'</span>, <span class="pl-s">'__eq__'</span>, <span class="pl-s">'__exit__'</span>, <span class="pl-s">'__format__'</span>, <span class="pl-s">'__ge__'</span>, <span class="pl-s">'__getattribute__'</span>, <span class="pl-s">'__gt__'</span>, <span class="pl-s">'__hash__'</span>, <span class="pl-s">'__init__'</span>, <span class="pl-s">'__init_subclass__'</span>, <span class="pl-s">'__iter__'</span>, <span class="pl-s">'__le__'</span>, <span class="pl-s">'__lt__'</span>, <span class="pl-s">'__ne__'</span>, <span class="pl-s">'__new__'</span>, <span class="pl-s">'__next__'</span>, <span class="pl-s">'__pyx_vtable__'</span>, <span class="pl-s">'__reduce__'</span>, <span class="pl-s">'__reduce_ex__'</span>, <span class="pl-s">'__repr__'</span>, <span class="pl-s">'__setattr__'</span>, <span class="pl-s">'__setstate__'</span>, <span class="pl-s">'__sizeof__'</span>, <span class="pl-s">'__str__'</span>, <span class="pl-s">'__subclasshook__'</span>, <span class="pl-s">'_source'</span>, <span class="pl-s">'callproc'</span>, <span class="pl-s">'close'</span>, <span class="pl-s">'connection'</span>, <span class="pl-s">'description'</span>, <span class="pl-s">'execute'</span>, <span class="pl-s">'executemany'</span>, <span class="pl-s">'fetchall'</span>, <span class="pl-s">'fetchmany'</span>, <span class="pl-s">'fetchone'</span>, <span class="pl-s">'lastrowid'</span>, <span class="pl-s">'nextset'</span>, <span class="pl-s">'returnvalue'</span>, <span class="pl-s">'rowcount'</span>, <span class="pl-s">'rownumber'</span>, <span class="pl-s">'setinputsizes'</span>, <span class="pl-s">'setoutputsize'</span>]</pre></div>
<h3 dir="auto">What you think should happen instead</h3>
<p dir="auto">For the <code class="notranslate">fetch_all_handler</code> common handler we should be using <code class="notranslate">cursor.description is not None</code> instead.<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1322635880" data-permission-text="Title is private" data-url="https://github.com/apache/airflow/issues/25412" data-hovercard-type="pull_request" data-hovercard-url="/apache/airflow/pull/25412/hovercard" href="https://github.com/apache/airflow/pull/25412">#25412</a> also suggested a rollback so we should take this into account.</p>
<p dir="auto">Ref: <a href="https://peps.python.org/pep-0249/#description" rel="nofollow">https://peps.python.org/pep-0249/#description</a></p>
<h3 dir="auto">How to reproduce</h3>
<h3 dir="auto">Import a sql hook (any sql hook inheriting <code class="notranslate">DbApiHook.run</code> should do):</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; from airflow.providers.microsoft.mssql.hooks.mssql import MsSqlHook
&gt;&gt;&gt; hk = MsSqlHook(&quot;localhost-mssql-docker-test&quot;)
&gt;&gt;&gt; hk.run(&quot;SELECT SUSER_SNAME();&quot;, handler=lambda c: c.fetchall())
[('sa',)]"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-k">from</span> <span class="pl-s1">airflow</span>.<span class="pl-s1">providers</span>.<span class="pl-s1">microsoft</span>.<span class="pl-s1">mssql</span>.<span class="pl-s1">hooks</span>.<span class="pl-s1">mssql</span> <span class="pl-k">import</span> <span class="pl-v">MsSqlHook</span>
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">hk</span> <span class="pl-c1">=</span> <span class="pl-v">MsSqlHook</span>(<span class="pl-s">"localhost-mssql-docker-test"</span>)
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">hk</span>.<span class="pl-en">run</span>(<span class="pl-s">"SELECT SUSER_SNAME();"</span>, <span class="pl-s1">handler</span><span class="pl-c1">=</span><span class="pl-k">lambda</span> <span class="pl-s1">c</span>: <span class="pl-s1">c</span>.<span class="pl-en">fetchall</span>())
[(<span class="pl-s">'sa'</span>,)]</pre></div>
<h3 dir="auto">Import the new <code class="notranslate">fetch_all_handler</code> and get an error</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; from airflow.providers.common.sql.hooks.sql import fetch_all_handler
&gt;&gt;&gt; hk.run(&quot;SELECT SUSER_SNAME();&quot;, handler=fetch_all_handler)
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
  File &quot;/home/gebo/.virtualenvs/airflow2.1/lib/python3.6/site-packages/airflow/hooks/dbapi.py&quot;, line 207, in run
    result = handler(cur)
  File &quot;&lt;stdin&gt;&quot;, line 2, in fetch_all_handler
AttributeError: 'pymssql._pymssql.Cursor' object has no attribute 'returns_rows'"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-k">from</span> <span class="pl-s1">airflow</span>.<span class="pl-s1">providers</span>.<span class="pl-s1">common</span>.<span class="pl-s1">sql</span>.<span class="pl-s1">hooks</span>.<span class="pl-s1">sql</span> <span class="pl-k">import</span> <span class="pl-s1">fetch_all_handler</span>
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">hk</span>.<span class="pl-en">run</span>(<span class="pl-s">"SELECT SUSER_SNAME();"</span>, <span class="pl-s1">handler</span><span class="pl-c1">=</span><span class="pl-s1">fetch_all_handler</span>)
<span class="pl-v">Traceback</span> (<span class="pl-s1">most</span> <span class="pl-s1">recent</span> <span class="pl-s1">call</span> <span class="pl-s1">last</span>):
  <span class="pl-v">File</span> <span class="pl-s">"&lt;stdin&gt;"</span>, <span class="pl-s1">line</span> <span class="pl-c1">1</span>, <span class="pl-s1">in</span> <span class="pl-c1">&lt;</span><span class="pl-s1">module</span><span class="pl-c1">&gt;</span>
  <span class="pl-v">File</span> <span class="pl-s">"/home/gebo/.virtualenvs/airflow2.1/lib/python3.6/site-packages/airflow/hooks/dbapi.py"</span>, <span class="pl-s1">line</span> <span class="pl-c1">207</span>, <span class="pl-s1">in</span> <span class="pl-s1">run</span>
    <span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-en">handler</span>(<span class="pl-s1">cur</span>)
  <span class="pl-v">File</span> <span class="pl-s">"&lt;stdin&gt;"</span>, <span class="pl-s1">line</span> <span class="pl-c1">2</span>, <span class="pl-s1">in</span> <span class="pl-s1">fetch_all_handler</span>
<span class="pl-v">AttributeError</span>: <span class="pl-s">'pymssql._pymssql.Cursor'</span> <span class="pl-s1">object</span> <span class="pl-s1">has</span> <span class="pl-s1">no</span> <span class="pl-s1">attribute</span> <span class="pl-s">'returns_rows'</span></pre></div>
<h3 dir="auto">Operating System</h3>
<p dir="auto">Ubuntu 20.04</p>
<h3 dir="auto">Versions of Apache Airflow Providers</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Deployment</h3>
<p dir="auto">Official Apache Airflow Helm Chart</p>
<h3 dir="auto">Deployment details</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Anything else</h3>
<p dir="auto">The new version would look like:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="def fetch_all_handler(cursor) -&gt; Optional[List[Tuple]]:
    &quot;&quot;&quot;Handler for DbApiHook.run() to return results&quot;&quot;&quot;
    # dbapi2 compliant way to check for cursor results:
    if cursor.description is not None:
        return cursor.fetchall()
    else:
        return None"><pre class="notranslate"><span class="pl-k">def</span> <span class="pl-en">fetch_all_handler</span>(<span class="pl-s1">cursor</span>) <span class="pl-c1">-&gt;</span> <span class="pl-v">Optional</span>[<span class="pl-v">List</span>[<span class="pl-v">Tuple</span>]]:
    <span class="pl-s">"""Handler for DbApiHook.run() to return results"""</span>
    <span class="pl-c"># dbapi2 compliant way to check for cursor results:</span>
    <span class="pl-k">if</span> <span class="pl-s1">cursor</span>.<span class="pl-s1">description</span> <span class="pl-c1">is</span> <span class="pl-c1">not</span> <span class="pl-c1">None</span>:
        <span class="pl-k">return</span> <span class="pl-s1">cursor</span>.<span class="pl-en">fetchall</span>()
    <span class="pl-k">else</span>:
        <span class="pl-k">return</span> <span class="pl-c1">None</span></pre></div>
<h3 dir="auto">Are you willing to submit PR?</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Yes I am willing to submit a PR!</li>
</ul>
<h3 dir="auto">Code of Conduct</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I agree to follow this project's <a href="https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md">Code of Conduct</a></li>
</ul>