<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p><br>
</p>
<br>
<div class="moz-cite-prefix">Le 27/03/17 à 10:55, Pavel Velikhov a
écrit :<br>
</div>
<blockquote
cite="mid:8716ACD7-C609-4F9D-B9AF-9DBDA8369381@gmail.com"
type="cite">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Hi Brice,
<div class=""><br class="">
<div>
<blockquote type="cite" class="">
<div class="">On 27 Mar 2017, at 10:17, Brice PARENT <<a
moz-do-not-send="true" href="mailto:contact@brice.xyz"
class="">contact@brice.xyz</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<meta content="text/html; charset=utf-8"
http-equiv="Content-Type" class="">
<div bgcolor="#FFFFFF" text="#000000" class="">
<p class="">I prefer this a lot to the original syntax,
and I really think this has much better chances to be
integrated (if such an integration had to be done, and
not kept as a separate module).</p>
<p class="">Also, maybe managing this with classes
instead of syntax could also be done easily (without
any change to Python), like this: <br class="">
</p>
<p class=""><tt class="">from pyql import PQL, Select,
For, Where, GroupBy, Let</tt></p>
<p class=""><tt class="">result = PQL(<br class="">
Select("x", "sum_y"),<br class="">
For</tt><tt class="">(</tt><tt class="">"x", </tt><tt
class="">range(</tt><tt class=""><span class="pl-c1">1</span></tt><tt
class="">,</tt><tt class=""><span class="pl-c1"> 8</span></tt><tt
class="">)</tt><tt class=""><span class="pl-k"></span></tt><tt
class=""><span class="pl-c1"></span></tt><tt
class=""><span class="pl-c1"></span></tt><tt
class=""><span class="pl-c1"></span></tt><tt
class="">),</tt><tt class=""><tt class=""><br
class="">
For</tt><tt class="">(</tt><tt class=""><span
class="pl-c1"></span></tt><tt class=""><span
class="pl-c1"></span></tt><tt class="">"</tt><tt
class="">y",</tt><tt class=""><span class="pl-k"></span></tt><tt
class=""> </tt><tt class=""><tt class="">range</tt>(</tt><tt
class=""><span class="pl-c1">1</span></tt><tt
class="">,</tt><tt class=""><span class="pl-c1"> 7</span></tt><tt
class="">)),<br class="">
</tt> Where(</tt><tt class=""><tt class="">lambda
x, y: x </tt><tt class=""><span class="pl-k">%</span></tt><tt
class=""> </tt><tt class=""><span class="pl-c1">2</span></tt><tt
class=""> </tt><tt class=""><span class="pl-k">==</span></tt><tt
class=""> </tt><tt class=""><span class="pl-c1">0</span></tt><tt
class=""> </tt><tt class=""><span class="pl-k">and</span></tt><tt
class=""> y </tt><tt class=""><span class="pl-k">%</span></tt><tt
class=""> </tt><tt class=""><span class="pl-c1">2</span></tt><tt
class=""> </tt><tt class=""><span class="pl-k">!=</span></tt><tt
class=""> </tt><tt class=""><span class="pl-c1">0</span></tt><tt
class=""> </tt><tt class=""><span class="pl-k">and</span></tt><tt
class=""> x </tt><tt class=""><span class="pl-k">></span></tt><tt
class=""> y, </tt>"x", "y"</tt><tt class="">),</tt><tt
class=""> # function, *[arguments to pass to the
function]<br class="">
Where(</tt><tt class=""><tt class=""><tt
class=""><tt class="">"sum_y", </tt></tt>lambda
</tt></tt><tt class=""><tt class=""><tt class="">sum_y</tt>:
</tt></tt><tt class=""><tt class=""><tt class="">sum_y</tt>
</tt><tt class=""><span class="pl-k">%</span></tt><tt
class=""> </tt><tt class=""><span class="pl-c1">2</span></tt><tt
class=""> </tt><tt class=""><span class="pl-k">!=</span></tt><tt
class=""> </tt><tt class=""><span class="pl-c1">0</span></tt><tt
class="">)</tt></tt><br class="">
<tt class=""> GroupBy("x"),<br class="">
Let(</tt><tt class=""><tt class=""><tt class="">"sum_y",
</tt>lambda y: sum(y), "y"</tt>)</tt><tt class=""><br
class="">
)</tt></p>
<div class=""><br class="">
</div>
</div>
</div>
</blockquote>
<div><br class="">
</div>
So here’s the deal: small queries will look pretty decent in
pretty much all paradigms, ORM, or PythonQL or your proposal.</div>
<div>Once they get bigger and combine multiple pain points (say
outerjoins, grouping and nested data) - then unless you have a</div>
<div>really clear and minimal language, folks will get confused
and lost.</div>
<div><br class="">
</div>
<div>We’ve gone through a few query languages that failed,
including XQuery and others, and the main reason was the need
to learn</div>
<div>a whole new language and a bunch of libraries, nobody
wanted to do it. So the main selling point behind PythonQL is:
its Python</div>
<div>that folks hopefully know already, with just a few
extensions.<br>
</div>
</div>
</blockquote>
I get it, but it's more a matter of perception. To me, the version I
described is just Python, while yours is Python + specific syntax.
As this syntax is only used in PyQL sub-language, it's not really
Python any more...<br>
Also, what I like with what I used, is that it is object-based,
which allows any part of the query to be reusable or built
dynamically. We might also extend such a PQL object's constructor to
embed automatically whatever default parameters or database
connection we want, or shared behaviours, like:<br>
<tt><br>
</tt><tt>class MyPQL(PQL):</tt><tt><br>
</tt><tt> def get_limit(self):</tt><tt><br>
</tt><tt> if self.limit is not None:</tt><tt><br>
</tt><tt> return self.limit</tt><tt><br>
</tt><tt><br>
</tt><tt> return 10</tt><tt><br>
</tt><tt> </tt><tt><br>
</tt><tt> def __init__(self, *args):</tt><tt><br>
</tt><tt> args.append(</tt><tt><span class="">Let(</span></tt><tt><span
class=""><span class=""><span class="">"sum_y", </span>lambda
y: sum(y), "y"</span>)</span></tt><tt><span class="">)</span></tt><tt><br>
</tt><tt><span class=""> </span></tt><tt><span class=""><tt>args.append(</tt>GroupBy("x"))<br>
</span></tt><tt> super().__init__(*args)</tt><tt><br>
</tt>
<p class=""><tt><span class="">result = </span></tt><tt><span
class=""><tt>MyPQL</tt>(<br class="">
Select("x", "sum_y"),<br class="">
For</span></tt><tt><span class="">(</span></tt><tt><span
class="">"x", </span></tt><tt><span class="">range(</span></tt><tt><span
class=""><span class="pl-c1">1</span></span></tt><tt><span
class="">,</span></tt><tt><span class=""><span class="pl-c1">
8</span></span></tt><tt><span class="">)</span></tt><tt><span
class=""><span class="pl-k"></span></span></tt><tt><span
class=""><span class="pl-c1"></span></span></tt><tt><span
class=""><span class="pl-c1"></span></span></tt><tt><span
class=""><span class="pl-c1"></span></span></tt><tt><span
class="">),</span></tt><tt><span class=""><span class=""><br
class="">
For</span><span class="">(</span><span class=""><span
class="pl-c1"></span></span><span class=""><span
class="pl-c1"></span></span><span class="">"</span><span
class="">y",</span><span class=""><span class="pl-k"></span></span><span
class=""> </span><span class=""><span class="">range</span>(</span><span
class=""><span class="pl-c1">1</span></span><span class="">,</span><span
class=""><span class="pl-c1"> 7</span></span><span class="">)),<br
class="">
</span> Where(</span></tt><tt><span class=""><span class="">lambda
x, y: x </span><span class=""><span class="pl-k">%</span></span><span
class=""> </span><span class=""><span class="pl-c1">2</span></span><span
class=""> </span><span class=""><span class="pl-k">==</span></span><span
class=""> </span><span class=""><span class="pl-c1">0</span></span><span
class=""> </span><span class=""><span class="pl-k">and</span></span><span
class=""> y </span><span class=""><span class="pl-k">%</span></span><span
class=""> </span><span class=""><span class="pl-c1">2</span></span><span
class=""> </span><span class=""><span class="pl-k">!=</span></span><span
class=""> </span><span class=""><span class="pl-c1">0</span></span><span
class=""> </span><span class=""><span class="pl-k">and</span></span><span
class=""> x </span><span class=""><span class="pl-k">></span></span><span
class=""> y, </span>"x", "y"</span></tt><tt><span class="">),</span></tt><tt><span
class=""><br class="">
Where(</span></tt><tt><span class=""><span class=""><span
class=""><span class="">"sum_y", </span></span>lambda </span></span></tt><tt><span
class=""><span class=""><span class="">sum_y</span>: </span></span></tt><tt><span
class=""><span class=""><span class="">sum_y</span> </span><span
class=""><span class="pl-k">%</span></span><span class=""> </span><span
class=""><span class="pl-c1">2</span></span><span class="">
</span><span class=""><span class="pl-k">!=</span></span><span
class=""> </span><span class=""><span class="pl-c1">0</span></span><span
class="">)</span></span></tt><tt><span class=""></span></tt><tt><span
class=""><br class="">
)</span></tt></p>
Big queries, this way, may be split into smaller parts. And it
allows you to do the following in a single query, instead of having
to write one big for each condition<tt><span class=""></span></tt><br>
<tt><span class=""></span></tt>
<p class=""><tt><span class="">where_from = [</span></tt><tt><span
class="">For</span></tt><tt><span class="">(</span></tt><tt><span
class="">"x", </span></tt><tt><span class="">range(</span></tt><tt><span
class=""><span class="pl-c1">1</span></span></tt><tt><span
class="">,</span></tt><tt><span class=""><span class="pl-c1">
8</span></span></tt><tt><span class="">)</span></tt><tt><span
class=""><span class="pl-k"></span></span></tt><tt><span
class=""><span class="pl-c1"></span></span></tt><tt><span
class=""><span class="pl-c1"></span></span></tt><tt><span
class=""><span class="pl-c1"></span></span></tt><tt><span
class="">),</span></tt><tt><span class=""><span class=""> For</span><span
class="">(</span><span class=""><span class="pl-c1"></span></span><span
class=""><span class="pl-c1"></span></span><span class="">"</span><span
class="">y",</span><span class=""><span class="pl-k"></span></span><span
class=""> </span><span class=""><span class="">range</span>(</span><span
class=""><span class="pl-c1">1</span></span><span class="">,</span><span
class=""><span class="pl-c1"> 7</span></span><span class="">))]</span></span></tt><tt><span
class=""><br>
where = [</span></tt><tt><span class="">Where(</span></tt><tt><span
class=""><span class="">lambda x, y: x </span><span class=""><span
class="pl-k">%</span></span><span class=""> </span><span
class=""><span class="pl-c1">2</span></span><span class="">
</span><span class=""><span class="pl-k">==</span></span><span
class=""> </span><span class=""><span class="pl-c1">0</span></span><span
class=""> </span><span class=""><span class="pl-k">and</span></span><span
class=""> y </span><span class=""><span class="pl-k">%</span></span><span
class=""> </span><span class=""><span class="pl-c1">2</span></span><span
class=""> </span><span class=""><span class="pl-k">!=</span></span><span
class=""> </span><span class=""><span class="pl-c1">0</span></span><span
class=""> </span><span class=""><span class="pl-k">and</span></span><span
class=""> x </span><span class=""><span class="pl-k">></span></span><span
class=""> y, </span>"x", "y"</span></tt><tt><span class="">)</span></tt><tt><span
class=""></span></tt><tt><span class="">]<br>
if filter_sum_y:<br>
</span></tt><tt><span class=""><tt><span class="">where</span></tt>.append(</span></tt><tt><span
class=""><tt><span class="">Where(</span></tt><tt><span
class=""><span class=""><span class=""><span class="">"sum_y",
</span></span>lambda </span></span></tt><tt><span
class=""><span class=""><span class="">sum_y</span>: </span></span></tt><tt><span
class=""><span class=""><span class="">sum_y</span> </span><span
class=""><span class="pl-k">%</span></span><span
class=""> </span><span class=""><span class="pl-c1">2</span></span><span
class=""> </span><span class=""><span class="pl-k">!=</span></span><span
class=""> </span><span class=""><span class="pl-c1">0</span></span><span
class="">)</span></span></tt><tt><span class=""></span></tt><tt><span
class=""></span></tt>)<br>
</span></tt><tt><span class=""><span class=""><br>
</span></span></tt><tt><span class=""><span class=""><tt><span
class="">if group_by is not None:<br>
</span></tt> grouping = </span></span></tt><tt><span
class=""></span></tt><tt><span class="">GroupBy("x")</span></tt><br>
</p>
<p class=""><tt><span class="">result = </span></tt><tt><span
class=""><tt>MyPQL</tt>(</span></tt><tt><span class=""><tt><span
class="">Select("x", "sum_y")</span></tt>, *where_from,
*where, *grouping)</span></tt></p>
Side note : I'm not a big database user, I mostly use ORMs (Django's
and PonyORM depending on the projects) to access PgSQL and SQLite
(for unit testing), so I might not even have use cases for what
you're trying to solve. I just give my point of view here to explain
what I think could be more easily integrated and (re)used. And as
I'm a big fan of the DRY mentality, I'm not a fan of the
syntax-chaining things (as well as I don't really like big nested
comprehensions).<br>
<br>
-Brice<br>
</body>
</html>