[web2py] Re: the Set class should be deprecated

2011-12-18 Thread Massimo Di Pierro
We do support something silimilar:

db(Query(db, db._adapter.EQ, db.mytable.myfield, value))>select()

but it is not advertised because this is an internal issue and do not
promise backward compatibility.

We also support

>>> e = Expression(db,"mytable.myfield LIKE 'value' ")
>>> db(db.mytable)(e)._select()

Where expression can be anything.

On Dec 18, 7:09 am, Alan Etkin  wrote:
> And what if DAL supported statements like this? I think it doesen't by
> now:
>
> db(Query(db.mytable.myfield, "mystringoperator", myvalue)).select()
>
> Would that be a possible to implement, enhanced way of querying the
> database for the framework?
> Does it follows B. Will A option?
>
> On 17 dic, 16:18, Massimo Di Pierro 
> wrote:
>
>
>
>
>
>
>
> > I am reading this over and over... "a == b is a boolean". I know what
> > you mean but it may be confusing to other users so I will clarify.
> > It is a boolean when a and b have values, else it is just an
> > expression. In dal, "a==b" is a query (an expression) that is
> > evaluated on every record and if it returns true the record is
> > selected (not unlike SQL).
>
> > So in
>
> > db(a == b).select() or the proposed (a==b).select()
>
> > (a==b) does not return a boolean.
>
> > Massimo
>
> > On Dec 17, 11:36 am, Alan Etkin  wrote:
>
> > > > @Alan Etkin
> > > > Actually, (db.mytable.id == 3) is neither a tuple or a bool. The ==
> > > > operator used on a field returns a Query object.
>
> > > Yes, you are right, what i was trying to say is that this:
>
> > > (a == b).select()
>
> > > is more confusing to me than the normal web2py instruction because in
> > > a python program the above sentence should call a method of a bool
> > > object:
>
> > > "...Comparisons yield boolean values: True or False..."


[web2py] Re: the Set class should be deprecated

2011-12-18 Thread Alan Etkin
And what if DAL supported statements like this? I think it doesen't by
now:

db(Query(db.mytable.myfield, "mystringoperator", myvalue)).select()

Would that be a possible to implement, enhanced way of querying the
database for the framework?
Does it follows B. Will A option?

On 17 dic, 16:18, Massimo Di Pierro 
wrote:
> I am reading this over and over... "a == b is a boolean". I know what
> you mean but it may be confusing to other users so I will clarify.
> It is a boolean when a and b have values, else it is just an
> expression. In dal, "a==b" is a query (an expression) that is
> evaluated on every record and if it returns true the record is
> selected (not unlike SQL).
>
> So in
>
> db(a == b).select() or the proposed (a==b).select()
>
> (a==b) does not return a boolean.
>
> Massimo
>
> On Dec 17, 11:36 am, Alan Etkin  wrote:
>
> > > @Alan Etkin
> > > Actually, (db.mytable.id == 3) is neither a tuple or a bool. The ==
> > > operator used on a field returns a Query object.
>
> > Yes, you are right, what i was trying to say is that this:
>
> > (a == b).select()
>
> > is more confusing to me than the normal web2py instruction because in
> > a python program the above sentence should call a method of a bool
> > object:
>
> > "...Comparisons yield boolean values: True or False..."
>
>


[web2py] Re: the Set class should be deprecated

2011-12-17 Thread Massimo Di Pierro
I am reading this over and over... "a == b is a boolean". I know what
you mean but it may be confusing to other users so I will clarify.
It is a boolean when a and b have values, else it is just an
expression. In dal, "a==b" is a query (an expression) that is
evaluated on every record and if it returns true the record is
selected (not unlike SQL).

So in

db(a == b).select() or the proposed (a==b).select()

(a==b) does not return a boolean.

Massimo

On Dec 17, 11:36 am, Alan Etkin  wrote:
> > @Alan Etkin
> > Actually, (db.mytable.id == 3) is neither a tuple or a bool. The ==
> > operator used on a field returns a Query object.
>
> Yes, you are right, what i was trying to say is that this:
>
> (a == b).select()
>
> is more confusing to me than the normal web2py instruction because in
> a python program the above sentence should call a method of a bool
> object:
>
> "...Comparisons yield boolean values: True or False..."


[web2py] Re: the Set class should be deprecated

2011-12-17 Thread Alan Etkin
> @Alan Etkin
> Actually, (db.mytable.id == 3) is neither a tuple or a bool. The ==
> operator used on a field returns a Query object.

Yes, you are right, what i was trying to say is that this:

(a == b).select()

is more confusing to me than the normal web2py instruction because in
a python program the above sentence should call a method of a bool
object:

"...Comparisons yield boolean values: True or False..."


[web2py] Re: the Set class should be deprecated

2011-12-17 Thread lyn2py
I'm new to web2py and python, but if this argument is purely
syntactic, I thought it would be
db(table.id > 0).select()
rather than
(db.table.id > 0).select()

Nonetheless, I'm good with what we have now, especially the ample
examples in the web2py book to help me get up to speed. DAL is great!


[web2py] Re: the Set class should be deprecated

2011-12-16 Thread Anthony

>
> Last argument, I promise.


I won't hold you to that. :-)
 

> The existence of Query and Set objects are not a hidden implementation
> details. For example, if the user is unaware of the presence of Query
> objects, db(db.mytable.id == 3) shouldn't make any sense, as
> db.mytable.id == 3 should return a boolean. How could passing a
> boolean to db() possibly encode the information that makes up a query?
>
Right, but your proposed alternative has the same problem:

(db.mytable.id > 0).select()

What's a boolean doing with a select() method, and how could it encode the 
information that makes up a query? Overloading operators to produce a Query 
object is just as magical either way, and it needs to be explained to users 
in either case. If passing what appears to be a boolean to a callable class 
to produce a set is confusing, then treating what appears to be a boolean 
as a set itself should also be confusing. If your problem is with 
overloading operators to produce a Query, then deprecating Set doesn't 
solve that.
 

> Learners should not be given the impression that 'DAL syntax' is
> anything but just Python code.
>
Well, Python does allow operator overloading, so it is Python code, but 
again, it does not appear you are proposing an alternative to the 
overloading.
 

> If learners take away the
> lesson that query expressions are a magic special case in Python
> itself, web2py is doing a disservice to those students.
>
Perhaps we could explain it better.
 

> Removing Set would make the syntax slightly cleaner, but that's not
> the important point: the comprehensible mental model of the objects is
> more important than the syntax.
>
To me, passing query syntax plus optional parameters to a db object to 
define a set of records evokes a fairly comprehensible mental model -- at 
least as comprehensible as applying a chain of methods to some query syntax 
to define a set of records.

Note, I'm not particularly against your proposed alternative (though I'm 
not crazy about the method chaining) -- I just don't find the case for it 
quite so compelling. It seems the operator overloading likely generates 
more confusion, and I don't think that is helped by the proposed syntax 
change.

Anthony



[web2py] Re: the Set class should be deprecated

2011-12-16 Thread Brian Will
Last argument, I promise.

Here's my version of your summary:

1. We have a connection object that represents a database.

2. From the Fields associated with this connection, Queries are
produced with Field's overloaded operators. Queries can also be
produced from combination of other Queries with the & | and ~
operators of Query itself. Certain options can be specified with Query
methods.

3. Once we have a Query representing a set of JOINS and predicates,
actual database operations are performed by invoking a Query's
methods, .select(), .delete(), etc.

> From the standpoint of the API, it doesn't really > matter that the query 
> becomes a Query object internally -- you just need to > know the query 
> syntax, and you pass your query syntax to the db object to > define your 
> records.

> Maybe it's better to think about it from the perspective of using the API
rather than worrying about the internal implementation.

The existence of Query and Set objects are not a hidden implementation
details. For example, if the user is unaware of the presence of Query
objects, db(db.mytable.id == 3) shouldn't make any sense, as
db.mytable.id == 3 should return a boolean. How could passing a
boolean to db() possibly encode the information that makes up a query?

Learners should not be given the impression that 'DAL syntax' is
anything but just Python code. These are Python expressions that
produce Python objects, not special cases. A Query is not syntax, it
is an object that can be assigned to variables and passed around.
Web2py, aside from its views, doesn't add any language on top of
Python, and this is an important virtue. If learners take away the
lesson that query expressions are a magic special case in Python
itself, web2py is doing a disservice to those students.

Removing Set would make the syntax slightly cleaner, but that's not
the important point: the comprehensible mental model of the objects is
more important than the syntax.


[web2py] Re: the Set class should be deprecated

2011-12-16 Thread Anthony
 

> >> Something like:
> >>  (db.mytable.id == 3).ignore_common_filters().select()
>
> > A bit ugly, and gets worse if we add more arguments in the future.
>
> Say in our API that we have a Cat type with some uncommon options for
> users to set. Which is the better approach for setting these options?
>
> A) add optional argument(s) to the constructor. B) add method(s) to
> modify the object state. C) add properties to assign. D) encapsulate
> the options in a wrapper class Feline.
>
D (though the wrapper class might be something more like GroomedCat, not a 
strict synonym)
 

> A), obviously, is the normal solution, but we can't do that with Query
> because we normally produce Query objects from overloaded operators of
> Field. Going with solution D) over B) or C) is a very odd thing to do.
>
Not sure why. It leads to nicer syntax.
 

> If D) served some other purpose, it might begin to make sense, but as
> I've already argued, it doesn't.
>
Why does the chosen solution have to serve more than one purpose?

Maybe it's better to think about it from the perspective of using the API 
rather than worrying about the internal implementation.

We have a connection object that represents a database:

db

db is callable -- calling it with a query plus some optional arguments 
defines a set of records in the database:

db(query, **optional_arguments)

The query involves special DAL syntax, applying various operators to table 
fields (behind the scenes, the DAL converts that to a Query object, but 
that's just an implementation detail). The optional arguments may further 
refine the set of records identified by the query.

Once we have defined a set of records, we can apply various methods to that 
set, such as select, count, delete, etc.

db(query, **optional_arguments).select(...)

That all seems fairly straightforward to me, and the syntax is clean. In 
this story, the query is just the DAL syntax for identifying particular 
records, whereas the set is defined both by the query syntax and the 
optional arguments. From the standpoint of the API, it doesn't really 
matter that the query becomes a Query object internally -- you just need to 
know the query syntax, and you pass your query syntax to the db object to 
define your records. Note, the Query class doesn't have any public methods 
to call, so the user doesn't need to explicitly think about the Query class 
-- all the action happens with the Set object. From the user perspective, 
there's query syntax and a Set object -- no need to worry about the 
internal details of the Query vs. Set classes. Perhaps there's a better 
alternative for the internal implementation, but the public API seems 
reasonable to me.

Anthony



[web2py] Re: the Set class should be deprecated

2011-12-16 Thread Brian Will
Apologies for dragging this out. I don't mean to be combative, but...

@pbreit
It's weird if you're told OR if you think about it (especially if you
aren't already very fluent in Python). If no one tells you, and if you
don't think about it, it's probably fine. Also, the query already
encapsulates the connection (Queries come from Fields which belong to
Tables which belong to connections), so Set doesn't add that
information either.

@Anthony
Yes, keeping ignore_common_filters and similar future options in the
query is much preferable to adding it to .select() et. al., so my
first solution is the way to go.

>> Something like:
>>  (db.mytable.id == 3).ignore_common_filters().select()

> A bit ugly, and gets worse if we add more arguments in the future.

Say in our API that we have a Cat type with some uncommon options for
users to set. Which is the better approach for setting these options?

A) add optional argument(s) to the constructor. B) add method(s) to
modify the object state. C) add properties to assign. D) encapsulate
the options in a wrapper class Feline.

A), obviously, is the normal solution, but we can't do that with Query
because we normally produce Query objects from overloaded operators of
Field. Going with solution D) over B) or C) is a very odd thing to do.
If D) served some other purpose, it might begin to make sense, but as
I've already argued, it doesn't.

(I suppose I should be thankful web2py didn't solve the problem with
metaclasses :P)


Re: [web2py] Re: the Set class should be deprecated

2011-12-16 Thread Jonathan Lundell
On Dec 16, 2011, at 1:44 AM, Brian Will wrote:

> I concede that for web2py's current user base, this is a minor point
> of null concern, but I feel it's a notable blemish in an otherwise
> exceptionally clean and well-thought-out API, and a few blemishes like
> this here and there can represent serious learning hurdles.

I'm with Brian on this general idea. The DAL really is fairly difficult to 
grasp, I think for at least two fundamental reasons. One is that the Python 
overloading is hidden and has to be learned or guessed. The other is that 
web2py is likely to attract developers (like me) who have limited experience 
with SQL. Consequently, it's highly desirable to reduce or eliminate anything 
in the DAL API that further confuses or complicates matters. 

(I also don't think it helps too much in this regard to have very different 
syntaxes for doing the same thing; it confuses us slow learners. Python is not 
Perl.)

[web2py] Re: the Set class should be deprecated

2011-12-16 Thread Anthony
On Friday, December 16, 2011 12:45:12 AM UTC-5, Brian Will wrote:
>
> Something like:
>
>  (db.mytable.id == 3).ignore_common_filters().select()
>
A bit ugly, and gets worse if we add more arguments in the future.
 

> Or:
>
>  (db.mytable.id == 3).select(ignore_common_filters=True)
>
Not ideal if the argument properly belongs to the query. Now you've got to 
add that argument to all the Set methods that deal with the query. Easier 
and more straightforward to make it an argument of Set.

At the very least, the docs should be updated to point out that Set is
> a legacy design mistake. As it is, learners will confuse themselves
> trying to justify its existence.
>
Given that Set allows the use of arguments that potentially modify the 
query, as noted above, I don't think we have to explain it as a design 
mistake. Perhaps simply explaining that fact will be sufficient to avoid 
confusion regarding why it exists.

Anthony
 


[web2py] Re: the Set class should be deprecated

2011-12-16 Thread pbreit
It just seems like you'd need to be told that db() is weird to think that 
it is weird. It would be difficult to come to the conclusion that db() is 
weird without instruction. Doubly so if you are accessing multiple 
databases.

[web2py] Re: the Set class should be deprecated

2011-12-16 Thread Brian Will
@pbreit
> Can't you just explain to people that this is how you query the db:
>
>       rows = db(db.item.id==1).select()
>
> How much is gained by dropping the "db"?

Programming is all about taking comprehensible pieces and piecing them
together for your own purposes. A rote formula of syntax that you
don't really understand only helps you do that one thing and
superficial variants thereof. Often taking your rote formula and
plugging in different values can get you pretty far, but at some point
it fails, leaving you lost and frustrated. Sometimes, by just
imitating formulas, you'll pick up what's really going on over time,
but not without extra effort, and often you just won't. In short,
programmers shouldn't use their tools (languages, libraries, etc.) as
if they're magic.

So I'm not saying Set is hard to use, I'm saying it's hard to truly
understand. In your example, not only is the DAL instance db being
invoked (which in itself is a weird allowance of Python), invoking a
DAL is the preferred means of producing Set objects rather than the
Set constructor itself. (And keep in mind that these oddities are on
top of producing Query objects from overloaded operators, which is one
of the most confusing features of Python.) Again, though, the main
issue is that Set just doesn't really do anything and so begs
explanation. Sure many students are happy to blindly just imitate a
formula, but that's a bad impulse that should be countered.

I concede that for web2py's current user base, this is a minor point
of null concern, but I feel it's a notable blemish in an otherwise
exceptionally clean and well-thought-out API, and a few blemishes like
this here and there can represent serious learning hurdles.


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread pbreit
I'm admittedly a novice but I don't find db(db.item.id==1).select() very 
difficult to understand.

(db.item.id==1).select() is kind of like ' '.join(li) that is so confusing 
to Python newbies.

Can't you just explain to people that this is how you query the db:

  rows = db(db.item.id==1).select()

How much is gained by dropping the "db"?


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread Brian Will
Something like:

 (db.mytable.id == 3).ignore_common_filters().select()

Or:

 (db.mytable.id == 3).select(ignore_common_filters=True)

'One way of doing it' is an argument for fixing it and officially
deprecating the old way. I'd sympathize with the objections more if it
meant actual legacy breakage, but that's not necessary in this case.

My main concern, though, is not syntactical but rather that Set
requires a good ~5 minute detour to explain that, 'This is the way it
is even though it doesn't make sense.' Again, we're talking about the
hardest to understand aspect of web2py. I'm sure you're familiar with
how most students new to web programming are very sketchy on the
relational model (or databases in general). Web2py takes that model
and abstracts it to Python in a clever but disorienting way. Every
measure that minimizes that confusion would pay dividends for
learners. I'm creating web2py learning material now, and DAL basics
are consistently the biggest challenge.

At the very least, the docs should be updated to point out that Set is
a legacy design mistake. As it is, learners will confuse themselves
trying to justify its existence.


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread Massimo Di Pierro
yes. Only one way of doing things. db(...) does not add too much
syntax.
Moreover db(..., ) allows space for example arguments to be passed
to the query for example db(query, ignore_common_filters=True) so
omitting the db(...) would be a shortcut with decreased functionality.

Massimo

On Dec 15, 12:41 pm, Anthony  wrote:
> On Thursday, December 15, 2011 12:30:43 PM UTC-5, Massimo Di Pierro wrote:
>
> > I have proposed this once and there was opposition to the change.
>
> Do you recall the arguments against?


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread Anthony

>
> @Anthony
> > Though I believe it joins tables by using the WHERE clause (as opposed to
> > JOIN, which is used when you pass the "join" or "left" argument to one of
> > Set's methods).
>
> When SQL does that, it itself is doing an implicit JOIN. It's really
> just a syntax convenience. The JOIN is logically there in the SQL,
> just unstated.
>
Of course. You said it "superficially resembles a WHERE clause". I was just 
saying it actually _is_ a WHERE clause, albeit one that implements a join. 
This is explained here: 
http://web2py.com/book/default/chapter/06#Inner-Joins.

Anthony 


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread Brian Will
@Massimo
So I'm not crazy, at least. Perhaps you can just add the Query and
Table methods, leaving Set "deprecated" but never removed. Isn't this
the current policy anyway? New learners would have a more sensical API
while existing users could stick with what they know. Learnability is
one of web2py's greatest strengths, and this would mitigate some
significant confusion in the DAL, one of web2py's most complicated and
conceptually hard to understand features.

@Anthony
> Though I believe it joins tables by using the WHERE clause (as opposed to
> JOIN, which is used when you pass the "join" or "left" argument to one of
> Set's methods).

When SQL does that, it itself is doing an implicit JOIN. It's really
just a syntax convenience. The JOIN is logically there in the SQL,
just unstated.

@Alan Etkin
Actually, (db.mytable.id == 3) is neither a tuple or a bool. The ==
operator used on a field returns a Query object.


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread Anthony
On Thursday, December 15, 2011 12:30:43 PM UTC-5, Massimo Di Pierro wrote:
>
> I have proposed this once and there was opposition to the change.


Do you recall the arguments against? 


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread Massimo Di Pierro
I have proposed this once and there was opposition to the change.

On Dec 15, 1:46 am, Brian Will  wrote:
> The problem is that Set is superfluous, oddly named, and thereby makes
> the whole DAL confusing to learners. I experienced this confusion
> myself when learning web2py, and now I find it's a problem when
> teaching web2py to others.
>
> A Query is not, as some web2py docs claim, just a WHERE clause. It
> superficially resembles a WHERE clause, but it also implicitly encodes
> the joining of tables. A Set only represents the same virtual set of
> rows that the Query it wraps, so why keep Set and its confusing name?
>
> Off the top of my head, here's the simplest fix:
>
> 1. The Query class should gain the Set methods, e.g.:
>
>     (db.mytable.id == 3).select()
>
> 2. And for queries/updates of a single table, give Table these methods
> as well, e.g.:
>
>     db.mytable.select()
>
> Instead of:
>
>     db().select(db.mytable.ALL)
>
> The special case db() is particularly confusing: all other Sets
> represent a Query, and a Query only represents multiple tables in the
> form of joins (which effectively means combining tables into one); the
> db() Set is the only case of a Set that represents multiple, unjoined
> tables. It's weird.
>
> I'm sure there are use cases I haven't accounted for, but unless there
> are under-the-hood concerns I'm not aware of, I think it fairly
> evident that Set can be gotten rid of without much fuss. Am I totally
> wrong?


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread Anthony

>
> A Query is not, as some web2py docs claim, just a WHERE clause. It
> superficially resembles a WHERE clause, but it also implicitly encodes
> the joining of tables.
>
Though I believe it joins tables by using the WHERE clause (as opposed to 
JOIN, which is used when you pass the "join" or "left" argument to one of 
Set's methods). 


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread Alan Etkin
Sorry, that is more likely to be a bool object with a select() method.
Since a single comparison is supposed to return such object and not a
sequence

On 15 dic, 10:14, Alan Etkin  wrote:
> > (db.mytable.id == 3).select()
>
> It appears as a one length tuple that has a select() method.
>
> Wouldn't such changes bring compatibility issues with former formats?


[web2py] Re: the Set class should be deprecated

2011-12-15 Thread Alan Etkin
> (db.mytable.id == 3).select()

It appears as a one length tuple that has a select() method.

Wouldn't such changes bring compatibility issues with former formats?