Lucky
>>> results = orm.select((orm.count(ju), ju.referrer_chat_id, ju.referrer_external) for ju in JoiningUser)
>>> results.first()
None
Lucky
Oh wait.
Lucky
Silly me, there were no data in that table
Lucky
No rows = no result = None
A
Hi all. I've had a good hunt through google and various github repos. I'm running into an error when using Pony ORM with PyPy on Ubuntu 18. Does anyone have any advice or similar experience?
With PyPy 7.3.1 installed, the issue is easily reproduced like so:
virtualenv -p pypy3 venv
source venv/bin/activate
pip install pony
python -c 'from pony.orm import Database; db = Database(); db.bind(provider="sqlite",filename=":memory:")'
This results in the following, for me:
A
Traceback (most recent call last):
File "./app.py", line 30, in <module>
db.bind(**db_params)
File "/tmp/whatever/venv-pypy/site-packages/pony/orm/core.py", line 769, in bind
self._bind(*args, **kwargs)
File "/tmp/whatever/venv-pypy/site-packages/pony/orm/core.py", line 791, in _bind
self.provider = provider_cls(*args, **kwargs)
File "/tmp/whatever/venv-pypy/site-packages/pony/orm/dbproviders/sqlite.py", line 328, in __init__
DBAPIProvider.__init__(provider, *args, **kwargs)
File "/tmp/whatever/venv-pypy/site-packages/pony/orm/dbapiprovider.py", line 130, in __init__
connection, is_new_connection = provider.connect()
File "<string>", line 2, in connect
File "/tmp/whatever/venv-pypy/site-packages/pony/orm/dbapiprovider.py", line 55, in wrap_dbapi_exceptions
try: return func(provider, *args, **kwargs)
File "/tmp/whatever/venv-pypy/site-packages/pony/orm/dbapiprovider.py", line 230, in connect
return provider.pool.connect()
File "/tmp/whatever/venv-pypy/site-packages/pony/orm/dbapiprovider.py", line 351, in connect
pool._connect()
File "/tmp/whatever/venv-pypy/site-packages/pony/orm/dbproviders/sqlite.py", line 671, in _connect
con.execute('PRAGMA foreign_keys = true')
File "/snap/pypy3/current/lib_pypy/_sqlite3.py", line 419, in execute
return cur.execute(*args)
File "/snap/pypy3/current/lib_pypy/_sqlite3.py", line 773, in wrapper
return func(self, *args, **kwargs)
File "/snap/pypy3/current/lib_pypy/_sqlite3.py", line 934, in execute
return self.__execute(False, sql, [params])
File "/snap/pypy3/current/lib_pypy/_sqlite3.py", line 884, in __execute
if self.__connection._begin_statement and self.__statement._is_dml:
AttributeError: 'Connection' object has no attribute '_begin_statement'
Alexander
It seems something wrong with sqlite3. I don't think this is directly related to Pony
A
Indeed. Hmm. Okay, thanks @metaprogrammer I'll continue my investigations!
A
Quick update: Seems to be some combination of PyPy + sqlite3. I was using PyPy 7.3.1 installed using snap. By uninstalling that and installing PyPy using apt instead, I'm not seeing this error.
Alexander
Ok, good to know
Evgeniy
Hello! Is it possible to use the one model for multiple databases?
Alexander
No, db object connects to database first to determine server version, as it may be important to know, what columns should be generated
But if you define entities inside a function, you can create several db objects and connect them to different databases
Evgeniy
Thank!
Anonymous
I need help with a query.
I have a Join table (see https://editor.ponyorm.com/user/luckydonald/channel_network/snapshots/176 )
query = orm.select(
(orm.count(j.id), j.joining_user is None, j.joining_user.referrer_chat_id, j.joining_user.referrer_external)
for j in Join
if j.chat.id == update.message.chat.id
).order_by(orm.desc(1))
Anonymous
Now I want to get the count of
- no j.joining_user
- each unique j.joining_user.referrer_chat_id
- each unique j.joining_user.referrer_external
Anonymous
This is how my joins look like
Anonymous
The generated Query:
SELECT COUNT(DISTINCT "j"."id"), "j"."joining_user" IS NULL, "joininguser"."referrer_chat_id", "joininguser"."referrer_external"
FROM "join" "j", "joininguser" "joininguser"
WHERE "j"."chat" = -1001496723017
AND "j"."joining_user" = "joininguser"."id"
GROUP BY "j"."joining_user" IS NULL, "joininguser"."referrer_chat_id", "joininguser"."referrer_external"
ORDER BY 1 DESC
Anonymous
Anonymous
With
SELECT COUNT("j"."id"), "joining_user" IS NULL AS "jan", "joininguser"."referrer_chat_id", "joininguser"."referrer_external"
FROM "join" "j"
FULL JOIN "joininguser" "joininguser" ON "j"."joining_user" = "joininguser"."id"
WHERE "j"."chat" = -1001496723017
GROUP BY "jan", "joininguser"."referrer_chat_id", "joininguser"."referrer_external"
ORDER BY 1 DESC
I could come closer to an correct result, but I think it's still missing one.
Anonymous
For reference: Here is a pure python implementation of the count:
with orm.db_session():
stats = {} # {(1,2) : 3} # Key = (referrer_chat_id, referrer_external) # Value = count
stats: Dict[Tuple[Union[None, int], Union[None, int]], int]
join: Join
for join in orm.select(join for join in Join if join.chat.id == update.message.chat.id):
key = (join.joining_user.referrer_chat_id, join.joining_user.referrer_external) if join.joining_user else (None, None)
if key not in stats:
stats[key] = 0
# end if
stats[key] += 1
# end for
# end with
Anonymous
So I think the problem sums up to me liking to include NULLs in the joining_user field,
with a select like
(
orm.count(j.id),
j.joining_user.referrer_chat_id if j.joining_user else None,
j.joining_user.referrer_external if j.joining_user else None
)
Instead of
(
orm.count(j.id),
j.joining_user.referrer_chat_id,
j.joining_user.referrer_external
)
Anonymous
Sadly that results in pony.orm.decompiling.DecompileError: Expression is too complex to decompile, try to pass query as string, e.g. select("x for x in Something")
Lucky
How do I order a select result randomly?
I tried select(x for x in Entity).random(), but that doesn't work because I have to specify a limit.
Using .order_by('random()') doesn't work either:
chat_network_cron_1 | )).order_by('random()')
chat_network_cron_1 | File "/usr/local/lib/python3.7/site-packages/pony/orm/core.py", line 5991, in order_by
chat_network_cron_1 | return query._order_by('order_by', *args)
chat_network_cron_1 | File "/usr/local/lib/python3.7/site-packages/pony/orm/core.py", line 6011, in _order_by
chat_network_cron_1 | return query._process_lambda(func, globals, locals, order_by=True)
chat_network_cron_1 | File "/usr/local/lib/python3.7/site-packages/pony/orm/core.py", line 6069, in _process_lambda
chat_network_cron_1 | func_id, func_ast, globals, locals, special_functions, const_functions, argnames or prev_translator.namespace)
chat_network_cron_1 | File "/usr/local/lib/python3.7/site-packages/pony/orm/asttranslation.py", line 360, in create_extractors
chat_network_cron_1 | pretranslator = PreTranslator(tree, globals, locals, special_functions, const_functions, outer_names)
chat_network_cron_1 | File "/usr/local/lib/python3.7/site-packages/pony/orm/asttranslation.py", line 276, in __init__
chat_network_cron_1 | translator.dispatch(tree)
chat_network_cron_1 | File "/usr/local/lib/python3.7/site-packages/pony/orm/asttranslation.py", line 285, in dispatch
chat_network_cron_1 | ASTTranslator.dispatch(translator, node)
chat_network_cron_1 | File "/usr/local/lib/python3.7/site-packages/pony/orm/asttranslation.py", line 42, in dispatch
chat_network_cron_1 | translator.call(post_method, node)
chat_network_cron_1 | File "/usr/local/lib/python3.7/site-packages/pony/orm/asttranslation.py", line 44, in call
chat_network_cron_1 | return method(translator, node)
chat_network_cron_1 | File "/usr/local/lib/python3.7/site-packages/pony/orm/asttranslation.py", line 338, in postCallFunc
chat_network_cron_1 | x = eval(expr, translator.globals, translator.locals)
chat_network_cron_1 | File "<string>", line 1, in <module>
chat_network_cron_1 | NameError: name 'random' is not defined
Matthew
You have to specify a limit, or select all results, but them in a list, then shuffle the list
Lucky
Is that a limitation of Postgres?
Matthew
I’m not sure, but if you have a huge amount of rows performance won’t be good whether you shuffle in python or postgres
Matthew
Try running a postgres query with “order by random”
Lucky
but if I limit and do that multiple times I would get duplicates
Matthew
What is your use case?
Lucky
Matthew
You could use raw sql from pony
Lucky
It's a cron job, and should process all items matched.
Matthew
Why do you need random ordering for the cron job?
Lucky
In case of an error it would always spam the first element, so if I do a random I can minimize that risk
Matthew
Maybe try doing newest first then
Matthew
Or catching and logging the error
Matthew
Or recording the last error on that row and not trying again for a certain amount of time
Matthew
You never add new rows?
Lucky
I guess limiting to the max int of the database will be the same effect.
Lucky
)).order_by(orm.raw_sql('RANDOM()')) works
Lucky
Thanks!
Lucky
Alexander
> How do I order a select result randomly?
You need to understand this is very slow, and the more rows will be in the table the worse it will get
The practical way is to go through rows in linear order, mark the current row as being processed, commit to be sure the update is saved and then process it and commit again to save the result of processing
Alexander
> Using .order_by('random()') doesn't work either
If you write Python code inside a query as a string, you still need to define all names used inside the code
Here you need to add from random import random at the beginning of your module
Alexander
So I think the problem sums up to me liking to include NULLs in the joining_user field,
with a select like
(
orm.count(j.id),
j.joining_user.referrer_chat_id if j.joining_user else None,
j.joining_user.referrer_external if j.joining_user else None
)
Instead of
(
orm.count(j.id),
j.joining_user.referrer_chat_id,
j.joining_user.referrer_external
)
Pony does not support decompiling if-expressions, but you can provide generator code as a text string, if-expressions are supported inside a strings:
query = orm.left_join("""
(
orm.count(j.id),
j.joining_user is None,
j.joining_user.referrer_chat_id if j.joining_user is None else None,
j.joining_user.referrer_external if j.joining_user is None else None
)
for j in Join
if j.chat.id == update.message.chat.id
"""
).order_by(-1)
Alexander
I didn't check this query, but I think it should work
Alexander
Maybe using left_join is enough:
query = orm.left_join(
(
orm.count(j.id),
j.joining_user is None,
j.joining_user.referrer_chat_id,
j.joining_user.referrer_external
)
for j in Join
if j.chat.id == update.message.chat.id
).order_by(-1)
Lucky
Ah, thanks a ton.
Anonymous
Hi there, I somehow broke a diagram in the online editor, maybe by editing in two browser tabs at the same time. When I want to open the diagram I get
{"msg":"Server error"}
Any possibility to rollback? Or even to delete? It's a private diagram and my counter still counts it.
Second question: wouldn't it be nice to have the possibility to import entities code into the online editor? Or is that already possible and I've just missed something?
Lucky
Lucky
And another #bug I face, multiline comments break the syntax.
Please either replace the linebreak with a space or make it intend under the started comment and start with a # too.
Lucky
There doesn't seem to be any progress on that editor.
Maybe you guys should think about open sourcing it, so people can implement the features they need (like proper import/export) or a few of the simple features I requested.
Lucky
Another feature I'm missing is custom export templates, so I can use the typing module to annotate the types of those db fields.
Alexander
AFAIK this bug is fixed but probably not deployed.
Muhammad
hi there, this is my first time using pony, my question is:
i have an exists mysql database, to use pony should i create models with tables first
or there is a method to work with pony without defining models
Muhammad
?
Alexander
Hi, you need to define entities which corresponds to existing tables
Muhammad
great, thank you
Anonymous
how can i get the last row in a table ?
Jim
myquery[-1]
Anonymous
myquery[-1]
not from a query instance.
from a model like this
Order.last()
Jim
Order.select()[:1] I guess. there is a first() but I don't know if there is a last()
Jim
sorry Order.select()[1] I mean
Jim
Oh forget I do it again
Jim
Order.select()[-1] for the last one and Order.select()[:-1] to get last item but as a list, like python slice
Anonymous
Anonymous
guys i am using this
option = Option.select(lambda o: o.id==1)
but the result keeps giving me
Option[1]
even when i want to get the first one like this:
option = Option.select(lambda o: o.id==1)[0]
it gives me Option[1] again
Matthew
Matthew
Jim
@Karrar_220 to get Option[1] you can do Option[1] or Option.get(id=1)
Lucky
Does Pony support a // b?
Alexander
yes
Alexander
Well, it understands // in Python, but I'm not sure it translates it to different SQL
Lucky
I need to have it to round down (floor) the result, actually.
Alexander
In SQL "/" for integer values works as "//" in Python.
So, to calculate "//" both operands should be integers
And for "/" equivalent at least one operand should be rational
Pony should add conversion to float or to int to correctly translate / and // to SQL, but currently it does not cast operands. I need to fix it #todo
Right now, if both operands are int and you use // in Python, the result will be correct in SQL
Lucky
I have a Channel object telling when it should have the cronjob post something, with a posting_interval and posting_offset.
Say interval = 20 and offset = 5 would result in every 20 minutes, shifted by 5 minutes:
00:05, 00:25, 00:45, 01:05, …, 23:45
I mean I have two different versions, one with // and one with modulo %, but don't know which one is better for performace.
delta = this_time_in_minutes - last_time_in_minutes # precomputed in python
return Channel.select(
lambda c:
(last_time_in_minutes - c.posting_offset) % c.posting_interval < delta
)
or
return Channel.select(
lambda c:
((this_time_in_minutes - c.posting_offset) // c.posting_interval) > ((last_time_in_minutes - c.posting_offset) // c.posting_interval)
)
Lucky
Alexander
If they are int in Python, they should be int in the database too