[web2py] Re: the Set class should be deprecated
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
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
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
> @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
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
> > 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
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
> >> 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
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
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
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
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
@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
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
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
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
> > @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
@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
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
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
> > 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
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
> (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?