Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Turtles all the way down

Turtles all the way down

Django has a wonderful ORM which allows construction of complex SQL queries. But just how do we get from Pony.objects.all() to SELECT ... FROM ponies_pony? Grab your boots, your mining helmet and your weapons of choice, we're going hunting in the ORM. Will there be dragons in the depths, or is it just turtles all the way down?

Marc Tamlyn

June 14, 2014
Tweet

More Decks by Marc Tamlyn

Other Decks in Technology

Transcript

  1. The ORM • Maps objects to underlying relational data store

    • Allows powerful expressions for interacting with that data store • How does it work?
  2. Model Manager Queryset Query Q WhereNode Manager.filter() Manager.get_queryset() Queryset.filter() Queryset._filter_or_exclude()

    Q() Query.add_q() Query._add_q() WhereNode() Query.build_filter() ! ! ! ! ! ! ! ! WhereNode.add()
  3. Model Manager Queryset Query Q WhereNode Manager.filter() Manager.get_queryset() Queryset.filter() Queryset._filter_or_exclude()

    Q() Query.add_q() Query._add_q() WhereNode() Query.build_filter() Query.solve_lookup_type() ! ! ! ! ! ! WhereNode.add()
  4. Model Manager Queryset Query Q WhereNode Manager.filter() Manager.get_queryset() Queryset.filter() Queryset._filter_or_exclude()

    Q() Query.add_q() Query._add_q() WhereNode() Query.build_filter() Query.solve_lookup_type() Query.prepare_lookup_value() ! ! ! ! ! ! WhereNode.add()
  5. Model Manager Queryset Query Q WhereNode Manager.filter() Manager.get_queryset() Queryset.filter() Queryset._filter_or_exclude()

    Q() Query.add_q() Query._add_q() WhereNode() Query.build_filter() Query.solve_lookup_type() Query.prepare_lookup_value() Query.setup_joins() Query.trim_joins() ! ! ! ! WhereNode.add()
  6. Model Manager Queryset Query Q WhereNode Col Manager.filter() Manager.get_queryset() Queryset.filter()

    Queryset._filter_or_exclude() Q() Query.add_q() Query._add_q() WhereNode() Query.build_filter() Query.solve_lookup_type() Query.prepare_lookup_value() Query.setup_joins() Query.trim_joins() Col() ! ! ! WhereNode.add()
  7. Model Manager Queryset Query Q WhereNode Col Manager.filter() Manager.get_queryset() Queryset.filter()

    Queryset._filter_or_exclude() Q() Query.add_q() Query._add_q() WhereNode() Query.build_filter() Query.solve_lookup_type() Query.prepare_lookup_value() Query.setup_joins() Query.trim_joins() Col() Query.build_lookup() ! WhereNode.add() WhereNode.add()
  8. Model Manager Queryset Query Q WhereNode Col Lookup Manager.filter() Manager.get_queryset()

    Queryset.filter() Queryset._filter_or_exclude() Q() Query.add_q() Query._add_q() WhereNode() Query.build_filter() Query.solve_lookup_type() Query.prepare_lookup_value() Query.setup_joins() Query.trim_joins() Col() Query.build_lookup() Exact() WhereNode.add() WhereNode.add()
  9. Model Manager Queryset Query Q WhereNode Col Lookup Manager.filter() Manager.get_queryset()

    Queryset.filter() Queryset._filter_or_exclude() Q() Query.add_q() Query._add_q() WhereNode() Query.build_filter() Query.solve_lookup_type() Query.prepare_lookup_value() Query.setup_joins() Query.trim_joins() Col() Query.build_lookup() Exact() WhereNode.add() WhereNode.add()
  10. Our query • qs # Queryset • qs.query # Query

    • qs.query.where # WhereNode • qs.query.where.children[0] # Exact • qs.query.where.children[0].lhs # Col • qs.query.where.children[0].rhs # False
  11. Our query • qs.query.tables # ['dragons__dragon'] • qs.query.alias_map # join

    info • qs.query.having • qs.query.order_by • qs.query.select • qs.query.low_mark / qs.query.high_mark
  12. Hang on a minute… • We don't have a Dragon()

    yet • How did we get to that SQL string?
  13. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query)
  14. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query) SQLCompiler.results_iter()
  15. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query) SQLCompiler.results_iter() SQLCompiler.execute_sql()
  16. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query) SQLCompiler.results_iter() SQLCompiler.execute_sql() SQLCompiler.as_sql()
  17. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query) SQLCompiler.results_iter() SQLCompiler.execute_sql() SQLCompiler.as_sql() 'SELECT' SQLCompiler.get_columns() SQLCompiler.get_default_columns()
  18. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query) SQLCompiler.results_iter() SQLCompiler.execute_sql() SQLCompiler.as_sql() 'SELECT' SQLCompiler.get_columns() SQLCompiler.get_default_columns() 'FROM' SQLCompiler.get_from_clause()
  19. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query) SQLCompiler.results_iter() SQLCompiler.execute_sql() SQLCompiler.as_sql() 'SELECT' SQLCompiler.get_columns() SQLCompiler.get_default_columns() 'FROM' SQLCompiler.get_from_clause() 'WHERE' SQLCompiler.compile(query.where) WhereNode.as_sql() Exact.as_sql() Col.as_sql()
  20. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query) SQLCompiler.results_iter() SQLCompiler.execute_sql() SQLCompiler.as_sql() 'SELECT' SQLCompiler.get_columns() SQLCompiler.get_default_columns() 'FROM' SQLCompiler.get_from_clause() 'WHERE' SQLCompiler.compile(query.where) WhereNode.as_sql() Exact.as_sql() Col.as_sql() connection.cursor.execute()
  21. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query) SQLCompiler.results_iter() SQLCompiler.execute_sql() SQLCompiler.as_sql() 'SELECT' SQLCompiler.get_columns() SQLCompiler.get_default_columns() 'FROM' SQLCompiler.get_from_clause() 'WHERE' SQLCompiler.compile(query.where) WhereNode.as_sql() Exact.as_sql() Col.as_sql() connection.cursor.execute() Dragon()
  22. Model Manager Queryset Query Q WhereNode Lookup Col ! SQLCompiler

    Queryset.iterator() Query.get_compiler() SQLCompiler(query) SQLCompiler.results_iter() SQLCompiler.execute_sql() SQLCompiler.as_sql() 'SELECT' SQLCompiler.get_columns() SQLCompiler.get_default_columns() 'FROM' SQLCompiler.get_from_clause() 'WHERE' SQLCompiler.compile(query.where) WhereNode.as_sql() Exact.as_sql() Col.as_sql() connection.cursor.execute() Dragon()
  23. Database agnosticism • DatabaseBackend • Comprises: • DatabaseOperations • DatabaseFeatures

    • DatabaseIntrospection • DatabaseValidation • DatabaseClient
  24. Custom lookups • New in Django 1.7 • Know how

    to represent their own SQL rather than relying on SQLCompiler • The Query Expression API • as_sql • as_vendorname for database agnosticism • output_type
  25. Expressions • New in Django 1.8? • Came out of

    a better way to model aggregation and allow for more complex aggregates • Flexible enough to be usable in order_by, values and custom indexes • Share the Query Expression API