SlideShare a Scribd company logo
1 of 88
Object-Relational Mapper
Alexey Malashkevich @ponyorm
What makes Pony ORM different?
Fast object-relational mapper
which uses Python generators for
writing database queries
A Python generator
(p.name for p in product_list if p.price > 100)
A Python generator vs a SQL query
SELECT p.name
FROM Products p
WHERE p.price > 100
(p.name for p in product_list if p.price > 100)
(p.name for p in product_list if p.price > 100)
SELECT p.name
FROM Products p
WHERE p.price > 100
A Python generator vs a SQL query
(p.name for p in product_list if p.price > 100)
SELECT p.name
FROM Products p
WHERE p.price > 100
A Python generator vs a SQL query
(p.name for p in product_list if p.price > 100)
SELECT p.name
FROM Products p
WHERE p.price > 100
A Python generator vs a SQL query
The same query in Pony
SELECT p.name
FROM Products p
WHERE p.price > 100
select(p.name for p in Product if p.price > 100)
• Pony ORM
• Django
• SQL Alchemy
Query syntax comparison
Pony ORM:
select(p for p in Product
if p.name.startswith('A') and p.image is None
or p.added.year < 2014)
Query syntax comparison
Django:
Product.objects.filter(
Q(name__startswith='A', image__isnull=True)
| Q(added__year__lt=2014))
Query syntax comparison
SQLAlchemy:
session.query(Product).filter(
(Product.name.startswith('A')
& (Product.image == None))
| (extract('year', Product.added) < 2014))
Query syntax comparison
session.query(Product).filter(
(Product.name.startswith('A') & (Product.image == None))
| (extract('year', Product.added) < 2014))
Query syntax comparison
Product.objects.filter(
Q(name__startswith='A', image__isnull=True)
| Q(added__year__lt=2014))
select(p for p in Product
if p.name.startswith('A') and p.image is None
or p.added.year < 2014)
Pony
Django
SQLAlchemy
Query translation
select(p for p in Product
if p.name.startswith('A') and p.image is None
or p.added.year < 2014)
• Translation from the bytecode is fast
• The bytecode translation result is cached
• The Python generator object is used as a
cache key
Python generator object
Building a query step by step
q = select(o for o in Order if o.customer.id == some_id)
q = q.filter(lambda o: o.state != 'DELIVERED')
q = q.filter(lambda o: len(o.items) > 2)
q = q.order_by(Order.date_created)
q = q[10:20]
SELECT "o"."id"
FROM "Order" "o"
LEFT JOIN "OrderItem" "orderitem-1"
ON "o"."id" = "orderitem-1"."order"
WHERE "o"."customer" = ?
AND "o"."state" <> 'DELIVERED'
GROUP BY "o"."id"
HAVING COUNT("orderitem-1"."ROWID") > 2
ORDER BY "o"."date_created"
LIMIT 10 OFFSET 10
How Pony translates generator
expressions to SQL?
Python generator to SQL translation
1. Decompile bytecode and restore AST
2. Translate AST to ‘abstract SQL’
3. Translate ‘abstract SQL’ to a specific SQL
dialect
Python generator to SQL translation
1. Decompile bytecode and restore AST
2. Translate AST to ‘abstract SQL’
3. Translate ‘abstract SQL’ to a concrete
SQL dialect
Bytecode decompilation
• Using the Visitor pattern
• Methods of the Visitor object correspond
the byte code commands
• Pony keeps fragments of AST at the stack
• Each method either adds a new part of AST
or combines existing parts
(a + b.c) in x.y
Bytecode decompilation
(a + b.c) in x.y
LOAD_GLOBAL a
LOAD_FAST b
LOAD_ATTR c
BINARY_ADD
LOAD_FAST x
LOAD_ATTR y
COMPARE_OP in
Bytecode decompilation
Bytecode decompilation
(a + b.c) in x.y
LOAD_GLOBAL a
LOAD_FAST b
LOAD_ATTR c
BINARY_ADD
LOAD_FAST x
LOAD_ATTR y
COMPARE_OP in
Stack
Bytecode decompilation
(a + b.c) in x.y
> LOAD_GLOBAL a
LOAD_FAST b
LOAD_ATTR c
BINARY_ADD
LOAD_FAST x
LOAD_ATTR y
COMPARE_OP in
Stack
Name('a')
Bytecode decompilation
(a + b.c) in x.y
LOAD_GLOBAL a
> LOAD_FAST b
LOAD_ATTR c
BINARY_ADD
LOAD_FAST x
LOAD_ATTR y
COMPARE_OP in
Stack
Name('b')
Name('a')
(a + b.c) in x.y
LOAD_GLOBAL a
LOAD_FAST b
> LOAD_ATTR c
BINARY_ADD
LOAD_FAST x
LOAD_ATTR y
COMPARE_OP in
Stack
Getattr(Name('b'), 'c')
Name('a')
Bytecode decompilation
(a + b.c) in x.y
LOAD_GLOBAL a
LOAD_FAST b
LOAD_ATTR c
> BINARY_ADD
LOAD_FAST x
LOAD_ATTR y
COMPARE_OP in
Stack
Add(Name('a'),
Getattr(Name('b'), 'c'))
Bytecode decompilation
Bytecode decompilation
(a + b.c) in x.y
LOAD_GLOBAL a
LOAD_FAST b
LOAD_ATTR c
BINARY_ADD
> LOAD_FAST x
LOAD_ATTR y
COMPARE_OP in
Stack
Name('x')
Add(Name('a'),
Getattr(Name('b'), 'c'))
Bytecode decompilation
(a + b.c) in x.y
LOAD_GLOBAL a
LOAD_FAST b
LOAD_ATTR c
BINARY_ADD
LOAD_FAST x
> LOAD_ATTR y
COMPARE_OP in
Stack
Getattr(Name('x'), 'y')
Add(Name('a'),
Getattr(Name('b'), 'c'))
Bytecode decompilation
(a + b.c) in x.y
LOAD_GLOBAL a
LOAD_FAST b
LOAD_ATTR c
BINARY_ADD
LOAD_FAST x
LOAD_ATTR y
> COMPARE_OP in
Stack
Compare('in',
Add(…), Getattr(…))
Abstract Syntax Tree (AST)
a
in
+
.c
b
.y
x
(a + b.c) in x.y
Python generator to SQL translation
1. Decompile bytecode and restore AST
2. Translate AST to ‘abstract SQL’
3. Translate ‘abstract SQL’ to a concrete
SQL dialect
What SQL it should be translated to?
a
in
+
.c
b
.y
x
(a + b.c) in x.y
It depends on variables types!
What SQL it should be translated to?
(a + b.c) in x.y
• If a and c are numbers, y is a collection
(? + "b"."c") IN (SELECT …)
• If a and c are strings, y is a collection
CONCAT(?, "b"."c") IN (SELECT …)
• If a, c and y are strings
“x"."y" LIKE CONCAT('%', ?, "b"."c", '%')
What SQL it should be translated to?
(a + b.c) in x.y
• The result of translation depends on types
• If the translator analyzes node types by
itself, the logic becomes too complex
• Pony uses Monads to keep it simple
(a + b.c) in x.y
AST to SQL Translation
• Encapsulates the node translation logic
• Generates the result of translation - ‘the
abstract SQL’
• Can combine itself with other monads
The translator delegates the logic of translation
to monads
A Monad
• StringAttrMonad
• StringParamMonad
• StringExprMonad
• StringConstMonad
• DatetimeAttrMonad
• DatetimeParamMonad
• ObjectAttrMonad
• CmpMonad
• etc…
Each monad defines a set of allowed operations and can
translate itself into a part of resulting SQL query
Monad types
AST Translation
• Using the Visitor pattern
• Walk the tree in depth-first order
• Create monads when leaving each node
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
StringExpr
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
StringExpr
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
StringExpr
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
StringExpr
Monad
ObjectIter
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
StringExpr
Monad
ObjectIter
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
StringExpr
Monad
ObjectIter
Monad
StringAttr
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
StringExpr
Monad
ObjectIter
Monad
StringAttr
Monad
(a + b.c) in x.y
AST to SQL Translation
in
.y
x
+
a .c
b
StringParam
Monad
ObjectIter
Monad
StringAttr
Monad
StringExpr
Monad
ObjectIter
Monad
StringAttr
Monad
Cmp
Monad
Abstract SQL
(a + b.c) in x.y
['LIKE', ['COLUMN', 't1', 'y'],
['CONCAT',
['VALUE', '%'], ['PARAM', 'p1'],
['COLUMN', 't2', 'c'], ['VALUE', '%']
]
]
Allows to put aside the SQL dialect differences
Python generator to SQL translation
1. Decompile bytecode and restore AST
2. Translate AST to ‘abstract SQL’
3. Translate ‘abstract SQL’ to a specific SQL
dialect
Specific SQL dialects
['LIKE', ['COLUMN', 't1', 'y'],
['CONCAT',
['VALUE', '%'], ['PARAM', 'p1'],
['COLUMN', 't2', 'c'], ['VALUE', '%']
]
]
MySQL:
`t1`.`y` LIKE CONCAT('%', ?, `t2`.`c`, '%')
SQLite:
"t1"."y" LIKE '%' || ? || "t2"."c" || '%'
Other Pony ORM features
• Identity Map
• Automatic query optimization
• N+1 Query Problem solution
• Optimistic transactions
• Online ER Diagram Editor
Django ORM
s1 = Student.objects.get(pk=123)
print s1.name, s1.group.id
s2 = Student.objects.get(pk=456)
print s2.name, s2.group.id
• How many SQL queries will be executed?
• How many objects will be created?
Django ORM
s1 = Student.objects.get(pk=123)
print s1.name, s1.group.id
s2 = Student.objects.get(pk=456)
print s2.name, s2.group.id
Student 123
Django ORM
s1 = Student.objects.get(pk=123)
print s1.name, s1.group.id
s2 = Student.objects.get(pk=456)
print s2.name, s2.group.id
Student 123 Group 1
Django ORM
s1 = Student.objects.get(pk=123)
print s1.name, s1.group.id
s2 = Student.objects.get(pk=456)
print s2.name, s2.group.id
Student 123
Student 456
Group 1
Django ORM
s1 = Student.objects.get(pk=123)
print s1.name, s1.group.id
s2 = Student.objects.get(pk=456)
print s2.name, s2.group.id
Student 123
Student 456
Group 1
Group 1
Pony ORM
s1 = Student[123]
print s1.name, s1.group.id
s2 = Student[456]
print s2.name, s2.group.id
Pony ORM – seeds, IdentityMap
s1 = Student[123]
print s1.name, s1.group.id
s2 = Student[456]
print s2.name, s2.group.id
Student 123
Group 1
Pony ORM – seeds, IdentityMap
s1 = Student[123]
print s1.name, s1.group.id
s2 = Student[456]
print s2.name, s2.group.id
Student 123
Group 1
seed
Pony ORM – seeds, IdentityMap
s1 = Student[123]
print s1.name, s1.group.id
s2 = Student[456]
print s2.name, s2.group.id
Student 123
Group 1
seed
Pony ORM – seeds, IdentityMap
s1 = Student[123]
print s1.name, s1.group.id
s2 = Student[456]
print s2.name, s2.group.id
Student 123
Student 456
Group 1
seed
Pony ORM – seeds, IdentityMap
s1 = Student[123]
print s1.name, s1.group.id
s2 = Student[456]
print s2.name, s2.group.id
Student 123
Student 456
Group 1
seed
Solution for the N+1 Query Problem
orders = select(o for o in Order if o.total_price > 1000) 
.order_by(desc(Order.id)).page(1, pagesize=5)
for o in orders:
print o.total_price, o.customer.name
1
SELECT o.id, o.total_price, o.customer_id,...
FROM "Order" o
WHERE o.total_price > 1000
ORDER BY o.id DESC
LIMIT 5
Order 1
Order 3
Order 4
Order 7
Order 9
Customer 1
Customer 4
Customer 7
Solution for the N+1 Query Problem
Order 1
Order 3
Order 4
Order 7
Order 9
Customer 1
Customer 4
Customer 7
Solution for the N+1 Query Problem
One SQL query
Solution for the N+1 Query Problem
1
1
SELECT c.id, c.name, …
FROM “Customer” c
WHERE c.id IN (?, ?, ?)
orders = select(o for o in Order if o.total_price > 1000) 
.order_by(desc(Order.id)).page(1, pagesize=5)
for o in orders:
print o.total_price, o.customer.name
SELECT o.id, o.total_price, o.customer_id,...
FROM "Order" o
WHERE o.total_price > 1000
ORDER BY o.id DESC
LIMIT 5
Automatic query optimization
select(c for c in Customer
if sum(c.orders.total_price) > 1000)
SELECT "c"."id", "c"."email", "c"."password", "c"."name",
"c"."country", "c"."address"
FROM "Customer" "c"
WHERE (
SELECT coalesce(SUM("order-1"."total_price"), 0)
FROM "Order" "order-1"
WHERE "c"."id" = "order-1"."customer"
) > 1000
SELECT "c"."id"
FROM "Customer" "c"
LEFT JOIN "Order" "order-1"
ON "c"."id" = "order-1"."customer"
GROUP BY "c"."id"
HAVING coalesce(SUM("order-1"."total_price"), 0) > 1000
Transactions
def transfer_money(id1, id2, amount):
account1 = Account.objects.get(pk=id1)
if account1.amount < amount:
raise ValueError('Not enough funds!')
account2 = Account.object.get(pk=id2)
account1.amount -= amount
account1.save()
account2.amount += amount
account2.save()
Django ORM
@transaction.atomic
def transfer_money(id1, id2, amount):
account1 = Account.objects.get(pk=id1)
if account1.amount < amount:
raise ValueError('Not enough funds!')
account2 = Account.object.get(pk=id2)
account1.amount -= amount
account1.save()
account2.amount += amount
account2.save()
Transactions
Django ORM
@transaction.atomic
def transfer_money(id1, id2, amount):
account1 = Account.objects 
.select_for_update.get(pk=id1)
if account1.amount < amount:
raise ValueError('Not enough funds!')
account2 = Account.objects 
.select_for_update.get(pk=id2)
account1.amount -= amount
account1.save()
account2.amount += amount
account2.save()
Transactions
Django ORM
@db_session
def transfer_money(id1, id2, amount):
account1 = Account[id1]
if account1.amount < amount:
raise ValueError('Not enough funds!')
account1.amount -= amount
Account[id2].amount += amount
Transactions
Pony ORM
db_session
• Pony tracks which objects where changed
• No need to call save()
• Pony saves all updated objects in a single
transaction automatically on leaving the
db_session scope
Transactions
UPDATE Account
SET amount = :new_value
WHERE id = :id
AND amount = :old_value
Optimistic Locking
Optimistic Locking
• Pony tracks attributes which were read and
updated
• If object wasn’t locked using the for_update
method, Pony uses the optimistic locking
automatically
Entity-Relationship Diagram Editor
https://editor.ponyorm.com
Entity-Relationship Diagram Editor
https://editor.ponyorm.com
Entity-Relationship Diagram Editor
https://editor.ponyorm.com
Main Pony ORM features:
• Using generators for database queries
• Identity Map
• Solution for N+1 Query Problem
• Automatic query optimization
• Optimistic transactions
• Online ER-diagram editor
Wrapping up
• Python 3
• Microsoft SQL Server support
• Improved documentation
• Migrations
• Ansync queries
Pony roadmap
• Site ponyorm.com
• Twitter @ponyorm
• Github github.com/ponyorm/pony
• ER-Diagram editor editor.ponyorm.com
• Installation: pip install pony
Thank you!
Pony ORM

More Related Content

What's hot

Ge aviation spark application experience porting analytics into py spark ml p...
Ge aviation spark application experience porting analytics into py spark ml p...Ge aviation spark application experience porting analytics into py spark ml p...
Ge aviation spark application experience porting analytics into py spark ml p...Databricks
 
[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark Applications
[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark Applications[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark Applications
[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark ApplicationsFuture Processing
 
Scalable and Flexible Machine Learning With Scala @ LinkedIn
Scalable and Flexible Machine Learning With Scala @ LinkedInScalable and Flexible Machine Learning With Scala @ LinkedIn
Scalable and Flexible Machine Learning With Scala @ LinkedInVitaly Gordon
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In JavaAndrei Solntsev
 
Getting the best performance with PySpark - Spark Summit West 2016
Getting the best performance with PySpark - Spark Summit West 2016Getting the best performance with PySpark - Spark Summit West 2016
Getting the best performance with PySpark - Spark Summit West 2016Holden Karau
 
Scala introduction
Scala introductionScala introduction
Scala introductionvito jeng
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101Ankur Gupta
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2José Paumard
 
Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016
Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016
Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016Holden Karau
 
Beyond shuffling - Strata London 2016
Beyond shuffling - Strata London 2016Beyond shuffling - Strata London 2016
Beyond shuffling - Strata London 2016Holden Karau
 
Profiling and optimization
Profiling and optimizationProfiling and optimization
Profiling and optimizationg3_nittala
 
Functional Programming in Java 8 - Lambdas and Streams
Functional Programming in Java 8 - Lambdas and StreamsFunctional Programming in Java 8 - Lambdas and Streams
Functional Programming in Java 8 - Lambdas and StreamsCodeOps Technologies LLP
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava SchmidtJavaDayUA
 
Kotlin Introduction with Android applications
Kotlin Introduction with Android applicationsKotlin Introduction with Android applications
Kotlin Introduction with Android applicationsThao Huynh Quang
 
NOSQL and Cassandra
NOSQL and CassandraNOSQL and Cassandra
NOSQL and Cassandrarantav
 
CMU TREC 2007 Blog Track
CMU TREC 2007 Blog TrackCMU TREC 2007 Blog Track
CMU TREC 2007 Blog Trackjelsas
 

What's hot (20)

Ge aviation spark application experience porting analytics into py spark ml p...
Ge aviation spark application experience porting analytics into py spark ml p...Ge aviation spark application experience porting analytics into py spark ml p...
Ge aviation spark application experience porting analytics into py spark ml p...
 
[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark Applications
[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark Applications[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark Applications
[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark Applications
 
Scalable and Flexible Machine Learning With Scala @ LinkedIn
Scalable and Flexible Machine Learning With Scala @ LinkedInScalable and Flexible Machine Learning With Scala @ LinkedIn
Scalable and Flexible Machine Learning With Scala @ LinkedIn
 
Kpi driven-java-development-fn conf
Kpi driven-java-development-fn confKpi driven-java-development-fn conf
Kpi driven-java-development-fn conf
 
Functional programming in java
Functional programming in javaFunctional programming in java
Functional programming in java
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
 
Getting the best performance with PySpark - Spark Summit West 2016
Getting the best performance with PySpark - Spark Summit West 2016Getting the best performance with PySpark - Spark Summit West 2016
Getting the best performance with PySpark - Spark Summit West 2016
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Advanced Relevancy Ranking
Advanced Relevancy RankingAdvanced Relevancy Ranking
Advanced Relevancy Ranking
 
Python Performance 101
Python Performance 101Python Performance 101
Python Performance 101
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
Java 8 Stream API (Valdas Zigas)
Java 8 Stream API (Valdas Zigas)Java 8 Stream API (Valdas Zigas)
Java 8 Stream API (Valdas Zigas)
 
Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016
Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016
Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016
 
Beyond shuffling - Strata London 2016
Beyond shuffling - Strata London 2016Beyond shuffling - Strata London 2016
Beyond shuffling - Strata London 2016
 
Profiling and optimization
Profiling and optimizationProfiling and optimization
Profiling and optimization
 
Functional Programming in Java 8 - Lambdas and Streams
Functional Programming in Java 8 - Lambdas and StreamsFunctional Programming in Java 8 - Lambdas and Streams
Functional Programming in Java 8 - Lambdas and Streams
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava Schmidt
 
Kotlin Introduction with Android applications
Kotlin Introduction with Android applicationsKotlin Introduction with Android applications
Kotlin Introduction with Android applications
 
NOSQL and Cassandra
NOSQL and CassandraNOSQL and Cassandra
NOSQL and Cassandra
 
CMU TREC 2007 Blog Track
CMU TREC 2007 Blog TrackCMU TREC 2007 Blog Track
CMU TREC 2007 Blog Track
 

Viewers also liked

Coffee. Duta Vladut-group 8213
Coffee. Duta Vladut-group 8213Coffee. Duta Vladut-group 8213
Coffee. Duta Vladut-group 8213Vlad Duţă
 
Xin (Crossroads)
Xin (Crossroads)Xin (Crossroads)
Xin (Crossroads)Xin Gu
 
Object-Relational Mapping for Dummies
Object-Relational Mapping for DummiesObject-Relational Mapping for Dummies
Object-Relational Mapping for DummiesGlobalLogic Ukraine
 
Doctrine 2 - Introduction
Doctrine 2 - IntroductionDoctrine 2 - Introduction
Doctrine 2 - IntroductionDiego Lewin
 
Cost-based query optimization in Apache Hive 0.14
Cost-based query optimization in Apache Hive 0.14Cost-based query optimization in Apache Hive 0.14
Cost-based query optimization in Apache Hive 0.14Julian Hyde
 
Jooctrine - Doctrine ORM in Joomla!
Jooctrine - Doctrine ORM in Joomla!Jooctrine - Doctrine ORM in Joomla!
Jooctrine - Doctrine ORM in Joomla!Herman Peeren
 
My little pony powerpoint
My little pony powerpointMy little pony powerpoint
My little pony powerpointleason2
 
Coffee Project Report S Mo Goltz
Coffee Project Report  S  Mo GoltzCoffee Project Report  S  Mo Goltz
Coffee Project Report S Mo GoltzMo Goltz
 
ORM: Object-relational mapping
ORM: Object-relational mappingORM: Object-relational mapping
ORM: Object-relational mappingAbhilash M A
 
Object Relational model for SQLIite in android
Object Relational model for SQLIite  in android Object Relational model for SQLIite  in android
Object Relational model for SQLIite in android yugandhar vadlamudi
 
Python PPT
Python PPTPython PPT
Python PPTEdureka!
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to PythonNowell Strite
 

Viewers also liked (14)

Coffee. Duta Vladut-group 8213
Coffee. Duta Vladut-group 8213Coffee. Duta Vladut-group 8213
Coffee. Duta Vladut-group 8213
 
Xin (Crossroads)
Xin (Crossroads)Xin (Crossroads)
Xin (Crossroads)
 
Object-Relational Mapping for Dummies
Object-Relational Mapping for DummiesObject-Relational Mapping for Dummies
Object-Relational Mapping for Dummies
 
Doctrine 2 - Introduction
Doctrine 2 - IntroductionDoctrine 2 - Introduction
Doctrine 2 - Introduction
 
#jd12nl Seblod 2
#jd12nl  Seblod 2#jd12nl  Seblod 2
#jd12nl Seblod 2
 
Cost-based query optimization in Apache Hive 0.14
Cost-based query optimization in Apache Hive 0.14Cost-based query optimization in Apache Hive 0.14
Cost-based query optimization in Apache Hive 0.14
 
Jooctrine - Doctrine ORM in Joomla!
Jooctrine - Doctrine ORM in Joomla!Jooctrine - Doctrine ORM in Joomla!
Jooctrine - Doctrine ORM in Joomla!
 
My little pony powerpoint
My little pony powerpointMy little pony powerpoint
My little pony powerpoint
 
Coffee Project Report S Mo Goltz
Coffee Project Report  S  Mo GoltzCoffee Project Report  S  Mo Goltz
Coffee Project Report S Mo Goltz
 
ORM: Object-relational mapping
ORM: Object-relational mappingORM: Object-relational mapping
ORM: Object-relational mapping
 
Object Relational model for SQLIite in android
Object Relational model for SQLIite  in android Object Relational model for SQLIite  in android
Object Relational model for SQLIite in android
 
MySQL 5.7 + JSON
MySQL 5.7 + JSONMySQL 5.7 + JSON
MySQL 5.7 + JSON
 
Python PPT
Python PPTPython PPT
Python PPT
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to Python
 

Similar to How Pony ORM translates Python generators to SQL queries

app4.pptx
app4.pptxapp4.pptx
app4.pptxsg4795
 
Creating the PromQL Transpiler for Flux by Julius Volz, Co-Founder | Prometheus
Creating the PromQL Transpiler for Flux by Julius Volz, Co-Founder | PrometheusCreating the PromQL Transpiler for Flux by Julius Volz, Co-Founder | Prometheus
Creating the PromQL Transpiler for Flux by Julius Volz, Co-Founder | PrometheusInfluxData
 
How do you create a programming language for the JVM?
How do you create a programming language for the JVM?How do you create a programming language for the JVM?
How do you create a programming language for the JVM?Federico Tomassetti
 
cppt-170218053903 (1).pptx
cppt-170218053903 (1).pptxcppt-170218053903 (1).pptx
cppt-170218053903 (1).pptxWatchDog13
 
CPP-overviews notes variable data types notes
CPP-overviews notes variable data types notesCPP-overviews notes variable data types notes
CPP-overviews notes variable data types notesSukhpreetSingh519414
 
Clojure: Simple By Design
Clojure: Simple By DesignClojure: Simple By Design
Clojure: Simple By DesignAll Things Open
 
A Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert FornalA Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert FornalQA or the Highway
 
015. Interface Python with MySQL.pdf
015. Interface Python with MySQL.pdf015. Interface Python with MySQL.pdf
015. Interface Python with MySQL.pdfSuneetaSingh28
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional ArchitectureJohn De Goes
 
Hive Functions Cheat Sheet
Hive Functions Cheat SheetHive Functions Cheat Sheet
Hive Functions Cheat SheetHortonworks
 
Real time, streaming advanced analytics, approximations, and recommendations ...
Real time, streaming advanced analytics, approximations, and recommendations ...Real time, streaming advanced analytics, approximations, and recommendations ...
Real time, streaming advanced analytics, approximations, and recommendations ...DataWorks Summit/Hadoop Summit
 
Boston Spark Meetup May 24, 2016
Boston Spark Meetup May 24, 2016Boston Spark Meetup May 24, 2016
Boston Spark Meetup May 24, 2016Chris Fregly
 
Writing good std::future&lt;c++>
Writing good std::future&lt;c++>Writing good std::future&lt;c++>
Writing good std::future&lt;c++>Anton Bikineev
 
Writing good std::future&lt;c++>
Writing good std::future&lt;c++>Writing good std::future&lt;c++>
Writing good std::future&lt;c++>corehard_by
 
Webscale PostgreSQL - JSONB and Horizontal Scaling Strategies
Webscale PostgreSQL - JSONB and Horizontal Scaling StrategiesWebscale PostgreSQL - JSONB and Horizontal Scaling Strategies
Webscale PostgreSQL - JSONB and Horizontal Scaling StrategiesJonathan Katz
 
Graph abstraction
Graph abstractionGraph abstraction
Graph abstractionopenCypher
 

Similar to How Pony ORM translates Python generators to SQL queries (20)

Compose Code Camp (1).pptx
Compose Code Camp (1).pptxCompose Code Camp (1).pptx
Compose Code Camp (1).pptx
 
app4.pptx
app4.pptxapp4.pptx
app4.pptx
 
Creating the PromQL Transpiler for Flux by Julius Volz, Co-Founder | Prometheus
Creating the PromQL Transpiler for Flux by Julius Volz, Co-Founder | PrometheusCreating the PromQL Transpiler for Flux by Julius Volz, Co-Founder | Prometheus
Creating the PromQL Transpiler for Flux by Julius Volz, Co-Founder | Prometheus
 
How do you create a programming language for the JVM?
How do you create a programming language for the JVM?How do you create a programming language for the JVM?
How do you create a programming language for the JVM?
 
cppt-170218053903 (1).pptx
cppt-170218053903 (1).pptxcppt-170218053903 (1).pptx
cppt-170218053903 (1).pptx
 
CPP-overviews notes variable data types notes
CPP-overviews notes variable data types notesCPP-overviews notes variable data types notes
CPP-overviews notes variable data types notes
 
Clojure: Simple By Design
Clojure: Simple By DesignClojure: Simple By Design
Clojure: Simple By Design
 
A Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert FornalA Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert Fornal
 
015. Interface Python with MySQL.pdf
015. Interface Python with MySQL.pdf015. Interface Python with MySQL.pdf
015. Interface Python with MySQL.pdf
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional Architecture
 
Apache HAWQ Architecture
Apache HAWQ ArchitectureApache HAWQ Architecture
Apache HAWQ Architecture
 
Hive Functions Cheat Sheet
Hive Functions Cheat SheetHive Functions Cheat Sheet
Hive Functions Cheat Sheet
 
Real time, streaming advanced analytics, approximations, and recommendations ...
Real time, streaming advanced analytics, approximations, and recommendations ...Real time, streaming advanced analytics, approximations, and recommendations ...
Real time, streaming advanced analytics, approximations, and recommendations ...
 
Boston Spark Meetup May 24, 2016
Boston Spark Meetup May 24, 2016Boston Spark Meetup May 24, 2016
Boston Spark Meetup May 24, 2016
 
07 php
07 php07 php
07 php
 
Presentaion
PresentaionPresentaion
Presentaion
 
Writing good std::future&lt;c++>
Writing good std::future&lt;c++>Writing good std::future&lt;c++>
Writing good std::future&lt;c++>
 
Writing good std::future&lt;c++>
Writing good std::future&lt;c++>Writing good std::future&lt;c++>
Writing good std::future&lt;c++>
 
Webscale PostgreSQL - JSONB and Horizontal Scaling Strategies
Webscale PostgreSQL - JSONB and Horizontal Scaling StrategiesWebscale PostgreSQL - JSONB and Horizontal Scaling Strategies
Webscale PostgreSQL - JSONB and Horizontal Scaling Strategies
 
Graph abstraction
Graph abstractionGraph abstraction
Graph abstraction
 

Recently uploaded

Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLionel Briand
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingShane Coughlan
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITmanoharjgpsolutions
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogueitservices996
 
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxRTS corp
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shardsChristopher Curtin
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecturerahul_net
 
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full RecordingOpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full RecordingShane Coughlan
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfRTS corp
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Rob Geurden
 
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonApplitools
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identityteam-WIBU
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxRTS corp
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptxVinzoCenzo
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slidesvaideheekore1
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfmaor17
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesVictoriaMetrics
 

Recently uploaded (20)

Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and Repair
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh IT
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogue
 
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecture
 
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full RecordingOpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...
 
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identity
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptxThe Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
The Role of IoT and Sensor Technology in Cargo Cloud Solutions.pptx
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptx
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slides
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdf
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 Updates
 

How Pony ORM translates Python generators to SQL queries

  • 2. What makes Pony ORM different? Fast object-relational mapper which uses Python generators for writing database queries
  • 3. A Python generator (p.name for p in product_list if p.price > 100)
  • 4. A Python generator vs a SQL query SELECT p.name FROM Products p WHERE p.price > 100 (p.name for p in product_list if p.price > 100)
  • 5. (p.name for p in product_list if p.price > 100) SELECT p.name FROM Products p WHERE p.price > 100 A Python generator vs a SQL query
  • 6. (p.name for p in product_list if p.price > 100) SELECT p.name FROM Products p WHERE p.price > 100 A Python generator vs a SQL query
  • 7. (p.name for p in product_list if p.price > 100) SELECT p.name FROM Products p WHERE p.price > 100 A Python generator vs a SQL query
  • 8. The same query in Pony SELECT p.name FROM Products p WHERE p.price > 100 select(p.name for p in Product if p.price > 100)
  • 9. • Pony ORM • Django • SQL Alchemy Query syntax comparison
  • 10. Pony ORM: select(p for p in Product if p.name.startswith('A') and p.image is None or p.added.year < 2014) Query syntax comparison
  • 12. SQLAlchemy: session.query(Product).filter( (Product.name.startswith('A') & (Product.image == None)) | (extract('year', Product.added) < 2014)) Query syntax comparison
  • 13. session.query(Product).filter( (Product.name.startswith('A') & (Product.image == None)) | (extract('year', Product.added) < 2014)) Query syntax comparison Product.objects.filter( Q(name__startswith='A', image__isnull=True) | Q(added__year__lt=2014)) select(p for p in Product if p.name.startswith('A') and p.image is None or p.added.year < 2014) Pony Django SQLAlchemy
  • 14. Query translation select(p for p in Product if p.name.startswith('A') and p.image is None or p.added.year < 2014) • Translation from the bytecode is fast • The bytecode translation result is cached • The Python generator object is used as a cache key Python generator object
  • 15. Building a query step by step q = select(o for o in Order if o.customer.id == some_id) q = q.filter(lambda o: o.state != 'DELIVERED') q = q.filter(lambda o: len(o.items) > 2) q = q.order_by(Order.date_created) q = q[10:20] SELECT "o"."id" FROM "Order" "o" LEFT JOIN "OrderItem" "orderitem-1" ON "o"."id" = "orderitem-1"."order" WHERE "o"."customer" = ? AND "o"."state" <> 'DELIVERED' GROUP BY "o"."id" HAVING COUNT("orderitem-1"."ROWID") > 2 ORDER BY "o"."date_created" LIMIT 10 OFFSET 10
  • 16. How Pony translates generator expressions to SQL?
  • 17. Python generator to SQL translation 1. Decompile bytecode and restore AST 2. Translate AST to ‘abstract SQL’ 3. Translate ‘abstract SQL’ to a specific SQL dialect
  • 18. Python generator to SQL translation 1. Decompile bytecode and restore AST 2. Translate AST to ‘abstract SQL’ 3. Translate ‘abstract SQL’ to a concrete SQL dialect
  • 19. Bytecode decompilation • Using the Visitor pattern • Methods of the Visitor object correspond the byte code commands • Pony keeps fragments of AST at the stack • Each method either adds a new part of AST or combines existing parts
  • 20. (a + b.c) in x.y Bytecode decompilation
  • 21. (a + b.c) in x.y LOAD_GLOBAL a LOAD_FAST b LOAD_ATTR c BINARY_ADD LOAD_FAST x LOAD_ATTR y COMPARE_OP in Bytecode decompilation
  • 22. Bytecode decompilation (a + b.c) in x.y LOAD_GLOBAL a LOAD_FAST b LOAD_ATTR c BINARY_ADD LOAD_FAST x LOAD_ATTR y COMPARE_OP in Stack
  • 23. Bytecode decompilation (a + b.c) in x.y > LOAD_GLOBAL a LOAD_FAST b LOAD_ATTR c BINARY_ADD LOAD_FAST x LOAD_ATTR y COMPARE_OP in Stack Name('a')
  • 24. Bytecode decompilation (a + b.c) in x.y LOAD_GLOBAL a > LOAD_FAST b LOAD_ATTR c BINARY_ADD LOAD_FAST x LOAD_ATTR y COMPARE_OP in Stack Name('b') Name('a')
  • 25. (a + b.c) in x.y LOAD_GLOBAL a LOAD_FAST b > LOAD_ATTR c BINARY_ADD LOAD_FAST x LOAD_ATTR y COMPARE_OP in Stack Getattr(Name('b'), 'c') Name('a') Bytecode decompilation
  • 26. (a + b.c) in x.y LOAD_GLOBAL a LOAD_FAST b LOAD_ATTR c > BINARY_ADD LOAD_FAST x LOAD_ATTR y COMPARE_OP in Stack Add(Name('a'), Getattr(Name('b'), 'c')) Bytecode decompilation
  • 27. Bytecode decompilation (a + b.c) in x.y LOAD_GLOBAL a LOAD_FAST b LOAD_ATTR c BINARY_ADD > LOAD_FAST x LOAD_ATTR y COMPARE_OP in Stack Name('x') Add(Name('a'), Getattr(Name('b'), 'c'))
  • 28. Bytecode decompilation (a + b.c) in x.y LOAD_GLOBAL a LOAD_FAST b LOAD_ATTR c BINARY_ADD LOAD_FAST x > LOAD_ATTR y COMPARE_OP in Stack Getattr(Name('x'), 'y') Add(Name('a'), Getattr(Name('b'), 'c'))
  • 29. Bytecode decompilation (a + b.c) in x.y LOAD_GLOBAL a LOAD_FAST b LOAD_ATTR c BINARY_ADD LOAD_FAST x LOAD_ATTR y > COMPARE_OP in Stack Compare('in', Add(…), Getattr(…))
  • 30. Abstract Syntax Tree (AST) a in + .c b .y x (a + b.c) in x.y
  • 31. Python generator to SQL translation 1. Decompile bytecode and restore AST 2. Translate AST to ‘abstract SQL’ 3. Translate ‘abstract SQL’ to a concrete SQL dialect
  • 32. What SQL it should be translated to? a in + .c b .y x (a + b.c) in x.y
  • 33. It depends on variables types! What SQL it should be translated to? (a + b.c) in x.y
  • 34. • If a and c are numbers, y is a collection (? + "b"."c") IN (SELECT …) • If a and c are strings, y is a collection CONCAT(?, "b"."c") IN (SELECT …) • If a, c and y are strings “x"."y" LIKE CONCAT('%', ?, "b"."c", '%') What SQL it should be translated to? (a + b.c) in x.y
  • 35. • The result of translation depends on types • If the translator analyzes node types by itself, the logic becomes too complex • Pony uses Monads to keep it simple (a + b.c) in x.y AST to SQL Translation
  • 36. • Encapsulates the node translation logic • Generates the result of translation - ‘the abstract SQL’ • Can combine itself with other monads The translator delegates the logic of translation to monads A Monad
  • 37. • StringAttrMonad • StringParamMonad • StringExprMonad • StringConstMonad • DatetimeAttrMonad • DatetimeParamMonad • ObjectAttrMonad • CmpMonad • etc… Each monad defines a set of allowed operations and can translate itself into a part of resulting SQL query Monad types
  • 38. AST Translation • Using the Visitor pattern • Walk the tree in depth-first order • Create monads when leaving each node
  • 39. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b
  • 40. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b
  • 41. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad
  • 42. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad
  • 43. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad
  • 44. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad
  • 45. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad
  • 46. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad
  • 47. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad
  • 48. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad StringExpr Monad
  • 49. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad StringExpr Monad
  • 50. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad StringExpr Monad
  • 51. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad StringExpr Monad ObjectIter Monad
  • 52. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad StringExpr Monad ObjectIter Monad
  • 53. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad StringExpr Monad ObjectIter Monad StringAttr Monad
  • 54. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad StringExpr Monad ObjectIter Monad StringAttr Monad
  • 55. (a + b.c) in x.y AST to SQL Translation in .y x + a .c b StringParam Monad ObjectIter Monad StringAttr Monad StringExpr Monad ObjectIter Monad StringAttr Monad Cmp Monad
  • 56. Abstract SQL (a + b.c) in x.y ['LIKE', ['COLUMN', 't1', 'y'], ['CONCAT', ['VALUE', '%'], ['PARAM', 'p1'], ['COLUMN', 't2', 'c'], ['VALUE', '%'] ] ] Allows to put aside the SQL dialect differences
  • 57. Python generator to SQL translation 1. Decompile bytecode and restore AST 2. Translate AST to ‘abstract SQL’ 3. Translate ‘abstract SQL’ to a specific SQL dialect
  • 58. Specific SQL dialects ['LIKE', ['COLUMN', 't1', 'y'], ['CONCAT', ['VALUE', '%'], ['PARAM', 'p1'], ['COLUMN', 't2', 'c'], ['VALUE', '%'] ] ] MySQL: `t1`.`y` LIKE CONCAT('%', ?, `t2`.`c`, '%') SQLite: "t1"."y" LIKE '%' || ? || "t2"."c" || '%'
  • 59. Other Pony ORM features • Identity Map • Automatic query optimization • N+1 Query Problem solution • Optimistic transactions • Online ER Diagram Editor
  • 60. Django ORM s1 = Student.objects.get(pk=123) print s1.name, s1.group.id s2 = Student.objects.get(pk=456) print s2.name, s2.group.id • How many SQL queries will be executed? • How many objects will be created?
  • 61. Django ORM s1 = Student.objects.get(pk=123) print s1.name, s1.group.id s2 = Student.objects.get(pk=456) print s2.name, s2.group.id Student 123
  • 62. Django ORM s1 = Student.objects.get(pk=123) print s1.name, s1.group.id s2 = Student.objects.get(pk=456) print s2.name, s2.group.id Student 123 Group 1
  • 63. Django ORM s1 = Student.objects.get(pk=123) print s1.name, s1.group.id s2 = Student.objects.get(pk=456) print s2.name, s2.group.id Student 123 Student 456 Group 1
  • 64. Django ORM s1 = Student.objects.get(pk=123) print s1.name, s1.group.id s2 = Student.objects.get(pk=456) print s2.name, s2.group.id Student 123 Student 456 Group 1 Group 1
  • 65. Pony ORM s1 = Student[123] print s1.name, s1.group.id s2 = Student[456] print s2.name, s2.group.id
  • 66. Pony ORM – seeds, IdentityMap s1 = Student[123] print s1.name, s1.group.id s2 = Student[456] print s2.name, s2.group.id Student 123 Group 1
  • 67. Pony ORM – seeds, IdentityMap s1 = Student[123] print s1.name, s1.group.id s2 = Student[456] print s2.name, s2.group.id Student 123 Group 1 seed
  • 68. Pony ORM – seeds, IdentityMap s1 = Student[123] print s1.name, s1.group.id s2 = Student[456] print s2.name, s2.group.id Student 123 Group 1 seed
  • 69. Pony ORM – seeds, IdentityMap s1 = Student[123] print s1.name, s1.group.id s2 = Student[456] print s2.name, s2.group.id Student 123 Student 456 Group 1 seed
  • 70. Pony ORM – seeds, IdentityMap s1 = Student[123] print s1.name, s1.group.id s2 = Student[456] print s2.name, s2.group.id Student 123 Student 456 Group 1 seed
  • 71. Solution for the N+1 Query Problem orders = select(o for o in Order if o.total_price > 1000) .order_by(desc(Order.id)).page(1, pagesize=5) for o in orders: print o.total_price, o.customer.name 1 SELECT o.id, o.total_price, o.customer_id,... FROM "Order" o WHERE o.total_price > 1000 ORDER BY o.id DESC LIMIT 5
  • 72. Order 1 Order 3 Order 4 Order 7 Order 9 Customer 1 Customer 4 Customer 7 Solution for the N+1 Query Problem
  • 73. Order 1 Order 3 Order 4 Order 7 Order 9 Customer 1 Customer 4 Customer 7 Solution for the N+1 Query Problem One SQL query
  • 74. Solution for the N+1 Query Problem 1 1 SELECT c.id, c.name, … FROM “Customer” c WHERE c.id IN (?, ?, ?) orders = select(o for o in Order if o.total_price > 1000) .order_by(desc(Order.id)).page(1, pagesize=5) for o in orders: print o.total_price, o.customer.name SELECT o.id, o.total_price, o.customer_id,... FROM "Order" o WHERE o.total_price > 1000 ORDER BY o.id DESC LIMIT 5
  • 75. Automatic query optimization select(c for c in Customer if sum(c.orders.total_price) > 1000) SELECT "c"."id", "c"."email", "c"."password", "c"."name", "c"."country", "c"."address" FROM "Customer" "c" WHERE ( SELECT coalesce(SUM("order-1"."total_price"), 0) FROM "Order" "order-1" WHERE "c"."id" = "order-1"."customer" ) > 1000 SELECT "c"."id" FROM "Customer" "c" LEFT JOIN "Order" "order-1" ON "c"."id" = "order-1"."customer" GROUP BY "c"."id" HAVING coalesce(SUM("order-1"."total_price"), 0) > 1000
  • 76. Transactions def transfer_money(id1, id2, amount): account1 = Account.objects.get(pk=id1) if account1.amount < amount: raise ValueError('Not enough funds!') account2 = Account.object.get(pk=id2) account1.amount -= amount account1.save() account2.amount += amount account2.save() Django ORM
  • 77. @transaction.atomic def transfer_money(id1, id2, amount): account1 = Account.objects.get(pk=id1) if account1.amount < amount: raise ValueError('Not enough funds!') account2 = Account.object.get(pk=id2) account1.amount -= amount account1.save() account2.amount += amount account2.save() Transactions Django ORM
  • 78. @transaction.atomic def transfer_money(id1, id2, amount): account1 = Account.objects .select_for_update.get(pk=id1) if account1.amount < amount: raise ValueError('Not enough funds!') account2 = Account.objects .select_for_update.get(pk=id2) account1.amount -= amount account1.save() account2.amount += amount account2.save() Transactions Django ORM
  • 79. @db_session def transfer_money(id1, id2, amount): account1 = Account[id1] if account1.amount < amount: raise ValueError('Not enough funds!') account1.amount -= amount Account[id2].amount += amount Transactions Pony ORM
  • 80. db_session • Pony tracks which objects where changed • No need to call save() • Pony saves all updated objects in a single transaction automatically on leaving the db_session scope Transactions
  • 81. UPDATE Account SET amount = :new_value WHERE id = :id AND amount = :old_value Optimistic Locking
  • 82. Optimistic Locking • Pony tracks attributes which were read and updated • If object wasn’t locked using the for_update method, Pony uses the optimistic locking automatically
  • 86. Main Pony ORM features: • Using generators for database queries • Identity Map • Solution for N+1 Query Problem • Automatic query optimization • Optimistic transactions • Online ER-diagram editor Wrapping up
  • 87. • Python 3 • Microsoft SQL Server support • Improved documentation • Migrations • Ansync queries Pony roadmap
  • 88. • Site ponyorm.com • Twitter @ponyorm • Github github.com/ponyorm/pony • ER-Diagram editor editor.ponyorm.com • Installation: pip install pony Thank you! Pony ORM