> Sorry, but what should do .list() ?
> it is a query? it is pre-fetched or cached?
>
The whole point of having an ORM, is for you to not have to worry about the
answer to that question - it's gonna do the optimal thing it can, based on
the circumstances in which it is called.
As I described, like 10 times already, ORMs are statefull - they have
cache-management built-in.
The question of how these cache-management is working, and so whether or
not you can trust it, is a long and complex question. Suffice it to say,
that there has been more than a decade of research into this issue, so it
is solved.
Just as example, if the list has objects in it, it will check that what it
has is up-to-date. If it is called within the context of a transaction that
is in progress, and it had already did a query for that beforehand within
the same transaction, than by ACID's "C of Consistency" rule, the code
should assume that it's cached-data is up-to-date. If between the
previously-called query, and this call, a transaction was ended and a new
one started, then according to ACID's "C of Consistency" rule, the code
should not assume that the data is up-to-date, and issue a query.
ORMs like SQLA's ORM do a 'Unit-Of-Work' patterns, in which these caches
are managed for you. Any transaction-commit invalidates the caches, so you
can guarantee consistency across transactions.
> What about if I need the cities of countries where main language is
> not Spanish, and population is above 1 millon?
>
ORMs allow you to attache filters for that, it really depends on the
implementation, but let's think of some options, shell we?
The most straight-forward approach I would suggest, is the layered-approach
- meaning, the ORM should use the DAL for that internally.
It should allow you to construct the filters yourself using the DAL, and
have mechanisms to facilitate attaching of filters to these attributes.
We can go into a discussion of how it will look like in an ORM in web2py in
each of the options - which would be the fun-part, I think - so let's see:
First, let's extend the schema and ORM example-definitions to include that:
db.define_table('Language', Field('Name', 'String'))
db.define_table('Continent', Field('Name', 'string'))
db.define_table('Country', Field('Name', 'string'), Field('Continent',
db.Continent))
db.define_table('City', Field('Name', 'string'), Field('Country', db.Country),
Field('Language', db.Language), Field('Population', 'Integer'))
@ORM(db.Language)
class Language:
pass
@ORM(db.City)
class City:
pass
@ORM(db.Country)
class Country:
pass
@ORM(db.Continent)
class Continent:
pass
>>> ...
>>> spanish = Language(Name='Spanish')
>>> french = Language(Name='French')
>>> france.City.Language = french
>>> ...
Then, we could devise to do any number of things:
We can build basic stuff like .isGraterThan() into the ORM classes, and do:
>>> ...
>>> [city for city in fance.City.list if \
city.Language is not spanish and city.Population.isGraterThan(1000000)]
[<City Name:Paris>]
It almost reads like plain English... Beautiful (!)
Alternatively, we could have a set of operators that we can give to a
filter function:
>>> ...
>>> from ORM.operators import not, moreThan
>>> france.City.where(
Language=not(spanish), Population=moreThan(1000000))
[<City Name:Paris>]
Lastly, we could let the developer filter objects using the DAL indirectly:
>>> ...
>>> france.City.FilterBy(
(City.Languase != spanish) & (City.Population > 1000000))
[<City Name:Paris>]
> Please, note that you are mixing a declarative query syntax (DAL),
> with an imperative one (ORM)
>
>
No, I am LAYERING imperative-syntax "on-top" of declarative one.
>
> I would like a elegant declarative syntax similar to LINQ, but in python:
>
> [city for db.City.ALL in db.City, db.Country if db.Country.Name ==
> 'France' and db.Country.id == db.City.country]
>
>
My first suggestion was way more readable.
> Sadly, there is NO possible way to archive a pythonic list
> comprenhension syntax that query the objects in the server side AFAIK
Not sure what you mean...
>
> Some libraries uses dis (python disassembler) and other internal &
> dirty python hacks to do something similar, please, see:
>
> http://www.aminus.net/geniusql/
>
> http://www.aminus.org/blogs/index.php/2008/04/22/linq-in-python?blog=2
>
> http://www.aminus.net/geniusql/chrome/common/doc/trunk/managing.html
>
> Note that web2py is much closer to the "pythonic expressions", but
> without the early / late binding and other issues described there ;-)
>
I will look into that.
This would require caching or storing previous queried record in
> memory (something like a singleton), or "is" will not work as you are
> expecting (it is for checking "identity")...
>
Exactly! This is exactly what SQLA is already doing - I explained that
before - it uses what it calls 'Identity Mapping' internally:
http://www.youtube.com/watch?v=woKYyhLCcnU#t=6382s<http://www.youtube.com/watch?v=woKYyhLCcnU>
** Time-coded link - watch the following 4 minutes *
> That could be also archived hacking "Row", but you should use == in
> python for this kind of comparision (equality)
>
>
Not is SQLA :)
Web2py *could *do that too.
> For you that are creating it, but I will not understand it in a first
> sight, so I prefer the DAL syntax that is a bit verbose but more
> uniform
>
There is no non-uniformity in SQLA syntax, as there are 2 layers that
are explicitly-different. Web2py could do that too.
> (at least I know what I'm doing in each step, or can get a SQL book
> and see how to "pythonize" the expression)
>
Same as in SQLA - again, I am suggesting "augmenting" the DAL with another
separate ORM layer - not replacing the DAL.
> A ORM is not more intuitive and will have a higher learning curve, and
> no formal / logical / math justification theory BTW
>
> An ORM is MUCH MORE intuitive, as my examples had demonstrated, and the
formal/logical/math justification would still apply within the DAL layer
that would still exist underneath.
--
---
You received this message because you are subscribed to the Google Groups
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.