Comments (5)
Ugh, we've also got strict_one
to deal with, and since the docs are autogenerated, we can't easily change that in code without mucking up the docs. :-/
Should we just change 1.0.0? :-(
from postgres.py.
I think we should. :-(
from postgres.py.
Now I'm worried about row
and rows
being too similar, introducing bugs where you thought you were calling one but were calling the other.
for row in db.row("SELECT * FROM foo"):
print(row)
vs.
for row in db.rows("SELECT * FROM foo"):
print(row)
vs.
for row in db.one("SELECT * FROM foo"):
print(row)
vs.
for row in db.many("SELECT * FROM foo"):
print(row)
vs.
for row in db.one("SELECT * FROM foo"):
print(row)
vs.
for row in db.rows("SELECT * FROM foo"):
print(row)
Perhaps the cognitive obstacle between one
and rows
is good, because it helps you not confuse them.
I've already confused one
and run
. I did:
db.one("CREATE TABLE foo (bar text)")
Now that we have strict checking on one
this raises postgres.TooFew: Got -1 rows instead of 1.
Otherwise you get psycopg2.ProgrammingError: no results to fetch
. (Hmmm ... makes me think maybe we should wrap one calls in a transaction and only commit them if there's exactly one row, because the table is still created here. Reticketed as #17.)
The confusion between one
and run
fails early and hard, when it fails:
- If you call one when you meant to call run:
- The query doesn't return one row and you get an exception (assuming you're using strict
one
checking—perhaps a good reason to). - The query does return one row and you have simply discarded it: not a problem.
- The query doesn't return one row and you get an exception (assuming you're using strict
- If you call
run
when you meant to callone
then you getNone
back, which if you are using strictone
checking will be a surprise—another good reason to use that. Since you'd otherwise be expecting adict
(assuming you're using the default ofRealDictCursor
) then the failure would probably manifest asTypeError: 'NoneType' object is not subscriptable
when you tried to dorow['foo']
.
By contrast if you were to call row
when you meant rows
you would get a dict
that you could still iterate over. The bug would then manifest when you tried to treat one of the scalar dict
values like a dict
. If you call rows
when you meant row
then you'd get a list
where you expect a dict
and you'd probably see TypeError: list indices must be integers, not str
.
In other words, strict one
checking makes it less harmful to confuse one
and run
than it is to confuse one
and rows
. Should we rename rows
to many
? That feels too ORM-y to me. For me it invokes many-to-many relationships and relational algebra, which is decidedly not what we're modeling in Python here. rows
is much more matter-of-fact, and fits better with the common case where you do:
for row in db.rows(SELECT, params):
print(row)
But geez, this whole thing started this morning because I found myself wanting to say run
/ one
/ many
. I don't like all
there because my vim mis-highlights it as a builtin. :-/ It's also three letters instead of four which makes it easier to confuse with one
(as well as run
, I suppose). many
fits fine semantically and it's longer than one
so that's a subtle hint.
for row in db.many(SELECT, params):
print(row)
I don't want to get into a holy war over ORMs so I shouldn't care about that factor. The question is what's going to be the most obvious API here and while there's probably not a "right" answer there's righter answers than others. I know it's annoying in CSS that it's vertical-align
and text-align
... why isn't it horizontal-align
? It should be parallel. If the goal is not to confuse them then one
and many
are certainly better than row
and rows
. Also, since we don't have to worry about the strict_one
problem then we could simply alias rows = many
and call it a day. I'm slightly annoyed that many
could return zero or one result, which technically aren't many. I guess I can tell myself that it's an announcement of willingness to receive: "I'm willing to receive one result. I'm willing to receive many results." Meh. Don't like it. It could also return 10 out of 100 possible rows and still be many
when we really want all rows, guaranteed. all
really fits better semantically, but three characters, too similar. The vim thing can't be a reason.
Has this cave pinched out yet?
from postgres.py.
Reopened for @tshepang.
We could use all
with a simple alias. We do advertise as being "an abstraction over psycopg2" so maintaining the association with DB-API 2.0 is relevant.
from postgres.py.
Sorry, it was a busy day here at work, so I didn't get a chance to visit this site, but I am quite satisfied with the choice you made... one
/ all
. I am also glad that you took the time to write such detailed thoughts.
from postgres.py.
Related Issues (20)
- cursor.get_cursor should return self HOT 2
- link to parent for nested types?
- maybe back_as should override dereferencing
- Gittip -> Gratipay HOT 1
- Don't check for column name restrictions when receiving a single expression HOT 1
- ORM register_model does not work outside of "public" schema HOT 1
- map nested composite types
- translate Postgres exceptions into Python exceptions
- integrate with tablib HOT 1
- conform to Records' API HOT 2
- port to asyncpg
- Safe interpolation of column names HOT 10
- cursors are brittle, can't reuse after exception HOT 3
- connection should have a get_cursor on it
- Seems unable to handle '/' in password for url_to_dsn HOT 1
- release 2.2.2 HOT 1
- The connection pooling is flawed
- The Connection API is confusing
- The docs are out of date HOT 6
- Casting of table rows
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from postgres.py.