
Colin
07.12.2016
08:15:56
Hello guy
I would like to discuss a diagram for the web creator.
This is about relations and that relations always have fields on both tables involved.
I would suggest something like this as an option (see image)
Guys* :)

Luckydonald
07.12.2016
08:20:01
Pony genernates you Fields in both classes, so you can reach one from another

Alexey
07.12.2016
08:29:06
that's correct - having the relationship attributes in both entities allows traversing these attributes, so you can reach one object from another.
Colin, let me understand, why you'd like to omit the relationship attribute in the User entity? How does it help?

Google

Alexey
07.12.2016
08:30:51
Actually, you are not the first person asking about this. My understanding is that this way it is more SQL table oriented, because in the database there is no column for this relationship in the 'User' table
probably we could have two views in the editor 'object view' and 'table view'. Another option is to have the relation attributes separated from the regular attributes - say data attributes at the top and relationship attributes under a line at the bottom in each entity

Colin
07.12.2016
08:34:17
are both relational fields created by pony actually created in the database or is this just in the code for representation?

Alexey
07.12.2016
08:35:00
the code only
for one-to-many relationship the field is created in one table only
you can see that if you open one of the specific database with SQL tab (SQLite, MySQL, etc)

Colin
07.12.2016
08:35:29
okey so in this case it only helps me in the overview of the online tool
the "object" and "table" view would be very nice

Alexey
07.12.2016
08:37:34
what technology are you using for working with the database, once the diagram is created?

Colin
07.12.2016
08:37:55
for now i using django models
and for sure postgres as database

Alexey
07.12.2016
08:45:12
btw, we plan to add Django tab, where you can get Django models for your diagram

Colin
07.12.2016
08:45:39
? thanks :)

Alexey
07.12.2016
08:46:43
what about having the attributes which will not be created as fields in the database of different color on the diagram? say gray?

Google

Colin
07.12.2016
08:47:41
would be helpful as well
the problem i have is that is gets very fast unclear

Luckydonald
07.12.2016
08:49:58
Another thing which struck me, was that you can't Zoom.

Colin
07.12.2016
08:50:14
yes me 2
have you ever used enterprise architect?

Alexey
07.12.2016
08:51:43
currently you can zoom using the browser zoom
never used the enterprise architect. what we can pick from it?

Luckydonald
07.12.2016
08:54:03
Is there planned to be able to import pony code?

Colin
07.12.2016
08:54:55
one cool thing is to create modules with specific models in each of them
from that you have a view in each module to see only the tables related and the relations to other module-tables

Alexey
07.12.2016
08:55:22

Colin
07.12.2016
08:57:33
sure

Alexey
07.12.2016
08:58:02
and the diagram?

Colin
07.12.2016
08:58:04
these are the modules and models inside
is just an example

Alexey
07.12.2016
08:58:50
ok, I see, thanks!
Sorry guys, I need to step out for an hour
But let's continue this conversation, it is very cool that you can give us your feedback

Colin
07.12.2016
08:59:23
oke bye :)

Luckydonald
07.12.2016
09:01:06
how that could be heplful? what workflow do you see in this case?
2 cases:
- apply changes in code easily or be able to create them in code first, and later visualize them
- there is currently no import at all, It would be handy if I could enter a database i created hundreds of commits earlier, to have a look at the data at that time.
Having really big databases/many tables, entering then manually can be a hassle.
Maybe there could be an import module for other models too. That part maybe open source, so users can contribute other mappers, e.g. Importing Django Models into Pony

Google

Colin
07.12.2016
09:02:42
yes would be very nice

Luckydonald
07.12.2016
09:03:20
But I often change models in Source code, and manual doing that in the editor later sometimes I tend to forget something.

Alexey
07.12.2016
10:42:37

Luckydonald
08.12.2016
19:40:12
The line
db_user.last_used = orm.raw_sql("NOW()")
Fails with
TypeError: Attribute WebSession.last_used: expected type is 'datetime'. Got: <pony.orm.ormtypes.RawSQL object at 0x7eff3eaf3b38>
The schema looks like this:
class WebSession(db.Entity):
id = PrimaryKey(UUID)
bot_token = Optional(str, nullable=True)
user = Optional(User)
web_token = Optional(str)
created = Required(datetime, sql_default='NOW()')
last_used = Required(datetime, sql_default='NOW()')

Alexander
08.12.2016
19:43:12
RawSQL is just a text inside an SQL query. It evaluates on the database side. If you perform change in Python, assign Python value:
from datetime import datetime
...
db_user.last_user = datetime.now()

Luckydonald
08.12.2016
19:43:50
I was hoping I could have used NOW() to be independent of the script time(zone).

Alexander
08.12.2016
19:48:05
Hmm, so you mean that that Raw SQL value just used when UPDATE command will be sent to the database later? Maybe we can add this in the future.
Until that, you can add a trigger which will update the column automatically:
http://stackoverflow.com/questions/9556474/how-do-i-automatically-update-a-timestamp-in-postgresql/26284695#26284695

Luckydonald
08.12.2016
20:07:37
Having my boring old Sticker search query again:
pairs = orm.select(
(st.sticker.file_id, max(st.date))
for st in StickerMessage
for t in st.sticker.tags
if (query_text.lower() in t.string.lower() or query_text == st.sticker.emoji)
).order_by(orm.desc(2), 1).limit(50, offset=offset)
How would I best exclude StickerMessages where any of the Tags t.string.lower() == "blocked tag"?

Alexander
08.12.2016
20:11:47
and not exists(t for t in st.sticker.tags if t.string.lower() == "blocked tag")

Luckydonald
08.12.2016
20:13:56
I already have for t in st.sticker.tags, this can't be integrated?

Alexander
08.12.2016
20:14:44
no, the one of the tags exists and the other is not

Luckydonald
08.12.2016
20:15:32
Right. Is that where correct? Or should that be if?

Alexander
08.12.2016
20:16:40
yes, it should be if

Luckydonald
08.12.2016
20:16:52
:D Thanks.
Awesome, works!

Alexey
08.12.2016
21:32:07
Awesome, works!
@luckydonald how do you find the resulting query witten with Pony? does it look simple and understandable for you?

Luckydonald
08.12.2016
21:36:38
I just think the two fors are strange, and not instantly to understand

Google

Alexey
08.12.2016
21:41:43
it would be interesting to compare this good real-life example of a long query with one written with other mappers


Alexander
08.12.2016
21:56:54
It is not necessary to use two `for`s here. The query can be rewritten as:
orm.select(
(st.sticker.file_id, max(st.date))
for st in StickerMessage
if (query_text == st.sticker.emoji
or orm.exists(t for t in st.sticker.tags if query_text.lower() in t.string.lower()))
and not orm.exists(t for t in st.sticker.tags if t.string.lower() == "nsfw")
).order_by(orm.desc(2), 1).limit(50, offset=offset)
Also, I don't think it is good to calculate t.string.lower() inside query, it is better to pre-calculate it in a separate column. If it is possible to check this string for exact equality instead of substring test, the query can be expressed a bit simpler:
orm.select(
(st.sticker.file_id, max(st.date))
for st in StickerMessage
if (query_text == st.sticker.emoji or query_string.lower() in st.sticker.tags.lowerercase)
and "nsfw" not in st.sticker.tags.lowercase)
).order_by(orm.desc(2), 1).limit(50, offset=offset)


Luckydonald
08.12.2016
22:22:23
How can I specify a contraint on multible colums to be unique?
I want Tag.string, .user, .message_id to be together unique.
It is not necessary to use two `for`s here. The query can be rewritten as:
orm.select(
(st.sticker.file_id, max(st.date))
for st in StickerMessage
if (query_text == st.sticker.emoji
or orm.exists(t for t in st.sticker.tags if query_text.lower() in t.string.lower()))
and not orm.exists(t for t in st.sticker.tags if t.string.lower() == "nsfw")
).order_by(orm.desc(2), 1).limit(50, offset=offset)
Also, I don't think it is good to calculate t.string.lower() inside query, it is better to pre-calculate it in a separate column. If it is possible to check this string for exact equality instead of substring test, the query can be expressed a bit simpler:
orm.select(
(st.sticker.file_id, max(st.date))
for st in StickerMessage
if (query_text == st.sticker.emoji or query_string.lower() in st.sticker.tags.lowerercase)
and "nsfw" not in st.sticker.tags.lowercase)
).order_by(orm.desc(2), 1).limit(50, offset=offset)
I'll have a look, thank you!
This is composite_key(string, user, message_id), right?


Alexander
08.12.2016
22:24:59
yes

Luckydonald
08.12.2016
22:25:10
Thanks
Will it be applied, when the table already exists?

Alexander
08.12.2016
22:30:31
I think it should. I go offline, will answer other questions tomorrow. Bye!

Luckydonald
08.12.2016
22:31:58
Thanks for your time!
Have a good night!
I can't get COUNT to work... :/
orm.select((t.string, orm.count(t.string)) for t in Tag).order_by(orm.desc(2), 1)
This returns ["MLP", 1] But the database definitly contains more than one
If instead of t.string I use t, there are indeeed multible results

Alexander
09.12.2016
23:05:41
When a specific attribute is specified inside count, pony counts distinct values of that attribute. In order to count total number of rows just write count() without any arguments, it translates to COUNT(*)

Luckydonald
09.12.2016
23:25:24
I want to count all equal strings
And generate a list with [string, COUNT]
E.g. 12x "MLP", 12x "Pony", 5x "Smiling"

Alexander
09.12.2016
23:30:26
then do 'select((t.string, orm.count()) for t in ...)'
or 'select((t.string, orm.count(t)) for t in ...)'
The former query means "for each string count number of rows", the later one means "for each string count number of distinct Tag objects", the result should be the same in your case

Luckydonald
09.12.2016
23:41:09
Which would be more efficient?

Alexander
10.12.2016
08:43:08
The first one, I think. The difference should not be large

Google

Serhii
10.12.2016
14:41:44
"In this case, even though the object had already been loaded to the cache, the query still had to be sent to the database because the name attribute is not a unique key. The database session cache will only be used if we lookup an object by its primary or unique key." https://docs.ponyorm.com/firststeps.html#getting-objects
If object would be in the cache and someone would change this row in database would be cached object updated or not?
I think here is answer on my questions https://docs.ponyorm.com/transactions.html#optimistic-concurrency-control


Alexander
10.12.2016
17:46:03
If Pony read an object which was already loaded in a current db_session, then Pony checks whether an attributes still holds the same value. There are four possible situations:
1) The column value is the same as previously, Pony does nothing;
2) The column value is updated in the database, but the attribute value was no read or modified by application code. In that case Pony updates the attribute value silently.
3) The application code has already read previous value of the attribute. In that case, it is possible that current state of db_session depends on the obsolete value which was read from the attribute, and to prevent possible inconsistency Pony throws UnrepeatableRead exception.
4) The value of column in the database is changed. An application code already assign a new value to the attribute without reading the previous value. In that case the "db value" of attribute will be updated silently and later during COMMIT it will be overwritten by newly assigned value


Serhii
10.12.2016
19:54:53
Thank you @akozlovsky for that clear explanation. By the way, I reed that you planned to include GrapQL into new PonyORM relase. When I see GraphQL query it seems stict and clear:
type Project {
name: String
tagline: String
contributors: [User]
}
In Python 3.6 will be variable annotaion, and table defination code coul be like this:
class Project:
name: str
tagline: str
contibutors: [User]
I think it could be cool thing to define db schemas
What do you think, guys?

Romet
10.12.2016
19:56:56
Agreed

Alexander
10.12.2016
20:05:29
Type is just a part of the information about attribute. Beside type, there are many other things, like is it nullable, is it unique, what a maximul leghts of a string attribute, etc. Regarding collection attributes, currently we have Set attributes only, but in the future we plan to add List attributes as well, so the square bracket syntax is not enough to declare all necessary information

Serhii
10.12.2016
20:06:40
What about typing library? There we could manually add custom types

Alexander
10.12.2016
20:07:26
Can you give an example

Serhii
10.12.2016
20:07:43
https://docs.python.org/3/library/typing.html#generics

Romet
10.12.2016
20:07:52
@akozlovsky with the new annotation system you can also just create custom types for annotation purposes

Alexander
10.12.2016
20:08:54
But what may be an example in context of ORM usage
Some simple use-case

Serhii
10.12.2016
20:10:31
For example it would be good for type checker

Alexander
10.12.2016
20:10:59
Can you give an example of code?