SlideShare una empresa de Scribd logo
1 de 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

Más contenido relacionado

La actualidad más candente

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
 

La actualidad más candente (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
 

Destacado

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
 

Destacado (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 a 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++>corehard_by
 
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
 
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 a 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
 
Presentaion
PresentaionPresentaion
Presentaion
 
07 php
07 php07 php
07 php
 
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
 

Último

A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 

Último (20)

Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 

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