<p dir="auto"><strong>Describe the bug</strong><br>
SQLAlchemy (on the latest master version) does not place correct parenthesis when using the <code class="notranslate">||</code> operator.</p>
<p dir="auto"><strong>Expected behavior</strong></p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="expr = type_coerce(Author.id + literal(1), types.String)
f = (Author.first_name + expr).label('f')
session.query(f).select_from(Author)"><pre class="notranslate"><span class="pl-s1">expr</span> <span class="pl-c1">=</span> <span class="pl-en">type_coerce</span>(<span class="pl-v">Author</span>.<span class="pl-s1">id</span> <span class="pl-c1">+</span> <span class="pl-en">literal</span>(<span class="pl-c1">1</span>), <span class="pl-s1">types</span>.<span class="pl-v">String</span>)
<span class="pl-s1">f</span> <span class="pl-c1">=</span> (<span class="pl-v">Author</span>.<span class="pl-s1">first_name</span> <span class="pl-c1">+</span> <span class="pl-s1">expr</span>).<span class="pl-en">label</span>(<span class="pl-s">'f'</span>)
<span class="pl-s1">session</span>.<span class="pl-en">query</span>(<span class="pl-s1">f</span>).<span class="pl-en">select_from</span>(<span class="pl-v">Author</span>)</pre></div>
<p dir="auto">I expect the following query:</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="SELECT author.first_name || (author.id + ?) AS f
FROM author"><pre class="notranslate"><span class="pl-k">SELECT</span> <span class="pl-c1">author</span>.<span class="pl-c1">first_name</span> <span class="pl-k">||</span> (<span class="pl-c1">author</span>.<span class="pl-c1">id</span> <span class="pl-k">+</span> ?) <span class="pl-k">AS</span> f
<span class="pl-k">FROM</span> author</pre></div>
<p dir="auto">Producing:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Name1
Name2
..."><pre class="notranslate"><code class="notranslate">Name1
Name2
...
</code></pre></div>
<p dir="auto">Instead SQLAlchemy generate the following query:</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="SELECT author.first_name || author.id + ? AS f
FROM author"><pre class="notranslate"><span class="pl-k">SELECT</span> <span class="pl-c1">author</span>.<span class="pl-c1">first_name</span> <span class="pl-k">||</span> <span class="pl-c1">author</span>.<span class="pl-c1">id</span> <span class="pl-k">+</span> ? <span class="pl-k">AS</span> f
<span class="pl-k">FROM</span> author</pre></div>
<p dir="auto">Leading to incorrect results:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="1
1
..."><pre class="notranslate"><code class="notranslate">1
1
...
</code></pre></div>
<p dir="auto">Unlike the SQL operator <code class="notranslate">+</code>, the operator <code class="notranslate">||</code> has the highest precedence.<br>
Therefore to interpret this query correctly parenthesis are needed.<br>
For more details see <a href="https://www.sqlite.org/lang_expr.html#operators" rel="nofollow">here</a></p>
<p dir="auto"><strong>Versions.</strong><br>
SQLAlchemy latest master version(<a href="https://github.com/sqlalchemy/sqlalchemy/commit/3b2c6692bd5df6fe4a37192dfdaed408e3be5e54">commit</a>)</p>
<p dir="auto"><strong>Have a nice day!</strong></p>
<p dir="auto"><strong>Describe the bug</strong></p>

<p dir="auto">It seems to me that <code class="notranslate">sqlalchemy</code> does not wrap an SQL expression with brackets when the function <code class="notranslate">type_coerce()</code> is used.</p>
<p dir="auto">I have the following query</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="mulExpr = type_coerce((Model.a * Model.b), types.Float).label('mulExpr')
divExpr = (Model.c / mulExpr).label('divExpr')
session.query(divExpr, mulExpr).select_from(Model)"><pre class="notranslate"><span class="pl-s1">mulExpr</span> <span class="pl-c1">=</span> <span class="pl-en">type_coerce</span>((<span class="pl-v">Model</span>.<span class="pl-s1">a</span> <span class="pl-c1">*</span> <span class="pl-v">Model</span>.<span class="pl-s1">b</span>), <span class="pl-s1">types</span>.<span class="pl-v">Float</span>).<span class="pl-en">label</span>(<span class="pl-s">'mulExpr'</span>)
<span class="pl-s1">divExpr</span> <span class="pl-c1">=</span> (<span class="pl-v">Model</span>.<span class="pl-s1">c</span> <span class="pl-c1">/</span> <span class="pl-s1">mulExpr</span>).<span class="pl-en">label</span>(<span class="pl-s">'divExpr'</span>)
<span class="pl-s1">session</span>.<span class="pl-en">query</span>(<span class="pl-s1">divExpr</span>, <span class="pl-s1">mulExpr</span>).<span class="pl-en">select_from</span>(<span class="pl-v">Model</span>)</pre></div>
<p dir="auto">The code generates the following SQL query when I ran it on <code class="notranslate">sqlite</code>.</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="SELECT Model.c / Model.a * Model.b AS &quot;divExpr&quot;, Model.a * Model.b AS &quot;mulExpr&quot;
FROM listing"><pre class="notranslate"><span class="pl-k">SELECT</span> <span class="pl-c1">Model</span>.<span class="pl-c1">c</span> <span class="pl-k">/</span> <span class="pl-c1">Model</span>.<span class="pl-c1">a</span> <span class="pl-k">*</span> <span class="pl-c1">Model</span>.<span class="pl-c1">b</span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">"</span>divExpr<span class="pl-pds">"</span></span>, <span class="pl-c1">Model</span>.<span class="pl-c1">a</span> <span class="pl-k">*</span> <span class="pl-c1">Model</span>.<span class="pl-c1">b</span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">"</span>mulExpr<span class="pl-pds">"</span></span>
<span class="pl-k">FROM</span> listing</pre></div>
<p dir="auto">However, I would expect the following query instead where the sub-expression <code class="notranslate">Model.a * Model.b</code> is wrapped by brackets.</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="SELECT Model.c / (Model.a * Model.b) AS &quot;divExpr&quot;, Model.a * Model.b AS &quot;mulExpr&quot;
FROM listing"><pre class="notranslate"><span class="pl-k">SELECT</span> <span class="pl-c1">Model</span>.<span class="pl-c1">c</span> <span class="pl-k">/</span> (<span class="pl-c1">Model</span>.<span class="pl-c1">a</span> <span class="pl-k">*</span> <span class="pl-c1">Model</span>.<span class="pl-c1">b</span>) <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">"</span>divExpr<span class="pl-pds">"</span></span>, <span class="pl-c1">Model</span>.<span class="pl-c1">a</span> <span class="pl-k">*</span> <span class="pl-c1">Model</span>.<span class="pl-c1">b</span> <span class="pl-k">AS</span> <span class="pl-s"><span class="pl-pds">"</span>mulExpr<span class="pl-pds">"</span></span>
<span class="pl-k">FROM</span> listing</pre></div>
<p dir="auto">Note that this issue only occurs when the function <code class="notranslate">type_coerce()</code> is applied to the sub-expression.</p>
<p dir="auto"><strong>Have a nice day!</strong></p>