Skip to content

Commit

Permalink
Pony ORM Release 0.6.1
Browse files Browse the repository at this point in the history
* Closed #65: Now the select(), filter(), order_by(), page(), limit(), random() methods can be applied to collection attributes
* Closed #105: Now you can pass globals and locals to the select() function
* Improved inheritance support in queries: select(x for x in BaseClass if x.subclass_attr == y)
* Now it is possible to do db.insert(SomeEntity, column1=x, column2=y) instead of db.insert(SomeEntity._table_, column1=x, column2=y)
* Discriminator attribute can be part of the composite index
* Now it is possible to specify the attribute name instead of the attribute itself in composite index
* Query statistics: global_stats_lock is deprecated, just use global_stats property without any locking
* New load() method for entity instances which retrieves all unloaded attributes except collections
* New load() method for collections, e.g. customer.orders.load()
* Enhanced error message when descendant classes declare attributes with the same name
* Fixed #98: Composite index can include attributes of base entity
* Fixed #106: incorrect loading of object which consists of primary key only
* Fixed pony.converting.check_email()
* Prefetching bug fixed: if collection is already fully loaded it shouldn't be loaded again
* Deprecated Entity.order_by(..) method was removed. Use Entity.select().order_by(...) instead
* Various performance enhancements
* Multiple bugs were fixed
  • Loading branch information
kozlovsky committed Feb 20, 2015
2 parents 46bd64b + e7d7deb commit 5282b2d
Show file tree
Hide file tree
Showing 17 changed files with 378 additions and 156 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
# Pony ORM Release 0.6.1 (2015-02-20)

* Closed #65: Now the select(), filter(), order_by(), page(), limit(), random() methods can be applied to collection attributes
* Closed #105: Now you can pass globals and locals to the select() function
* Improved inheritance support in queries: select(x for x in BaseClass if x.subclass_attr == y)
* Now it is possible to do db.insert(SomeEntity, column1=x, column2=y) instead of db.insert(SomeEntity._table_, column1=x, column2=y)
* Discriminator attribute can be part of the composite index
* Now it is possible to specify the attribute name instead of the attribute itself in composite index
* Query statistics: global_stats_lock is deprecated, just use global_stats property without any locking
* New load() method for entity instances which retrieves all unloaded attributes except collections
* New load() method for collections, e.g. customer.orders.load()
* Enhanced error message when descendant classes declare attributes with the same name
* Fixed #98: Composite index can include attributes of base entity
* Fixed #106: incorrect loading of object which consists of primary key only
* Fixed pony.converting.check_email()
* Prefetching bug fixed: if collection is already fully loaded it shouldn't be loaded again
* Deprecated Entity.order_by(..) method was removed. Use Entity.select().order_by(...) instead
* Various performance enhancements
* Multiple bugs were fixed


# Pony ORM Release 0.6 (2014-11-05)

* Fixed #94: Aggregated subquery bug fixed
Expand Down
5 changes: 3 additions & 2 deletions doc/database.txt
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,11 @@ Methods for raw SQL access
Before executing this method, Pony flushes all the changes from the cache using the :ref:`flush() <flush_ref>` method.

.. py:method:: insert(table_name, returning=None, **kwargs)
insert(entity, returning=None, **kwargs)

Insert new rows into a table. This command bypasses the identity map cache and can be used in order to increase the performance when we need to create a lot of objects and not going to read them in the same transaction. Also you can use the ``db.execute()`` method for this purpose. If we need to work with those objects in the same transaction it is better to create instances of entities and have Pony to save them in the database on ``commit()``.
Insert new rows into a table. This command bypasses the identity map cache and can be used in order to increase the performance when we need to create a lot of objects and not going to read them in the same transaction. Also you can use the ``db.execute()`` method for this purpose. If you need to work with those objects in the same transaction it is better to create instances of entities and have Pony to save them in the database on ``commit()``.

``table_name`` - is the name of the table into which the data will be inserted, the name is case sensitive.
``table_name`` - is the name of the table into which the data will be inserted, the name is case sensitive. Instead of the ``table_name`` you can use the ``entity`` class. In this case Pony will insert into the table associated with the ``entity``.

The ``returning`` parameter allows you to specify the name of the column that holds the automatically generated primary key. If you want the ``insert`` method to return the value which is generated by the database, you should specify the name of the primary key column::

Expand Down
9 changes: 9 additions & 0 deletions doc/entities.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,17 @@ Using the ``composite_index()`` directive you can create a composite index for s
b = Optional(int)
composite_index(a, b)

You can use the attribute or the attribute name::

class Example(db.Entity):
a = Required(str)
b = Optional(int)
composite_index(a, 'b')

If you want to create a non-unique index for just one column, you can specify the ``index`` option of an attribute. This option is described later in this chapter.

The composite index can include a discriminator attribute used for inheritance.


Attribute data types
--------------------------
Expand Down
6 changes: 5 additions & 1 deletion doc/queries.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Pony provides a very convenient way to query the database using the generator ex
Pony ORM functions used to query the database
--------------------------------------------------------------------

.. py:function:: select(gen)
.. py:function:: select(gen[, globals[, locals])

This function translates the generator expression into SQL query and returns an instance of the :py:class:`Query` class. If necessary, you can apply any :py:class:`Query` method to the result, e.g. :py:meth:`Query.order_by` or :py:meth:`Query.count`. If you just need to get a list of objects you can either iterate over the result or get a full slice::

Expand All @@ -24,6 +24,10 @@ Pony ORM functions used to query the database

select((p.name, count(p.orders)) for p in Product)

You can pass the ``globals`` and ``locals`` dictionaries for using them as global and local namespace.

Also, you can apply the ``select`` method to relationship attributes. See :ref:`the examples <col_queries_ref>`

.. py:function:: get(gen)

Extracts one entity instance from the database. The function returns the object if an object with the specified parameters exists, or ``None`` if there is no such object. If there are more than one objects with the specified parameters, raises the ``MultipleObjectsFoundError: Multiple objects were found. Use select(...) to retrieve them`` exception. Example::
Expand Down
8 changes: 8 additions & 0 deletions doc/working_with_entity_instances.txt
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,14 @@ Entity class methods

If you need to use ``SELECT ... FOR UPDATE`` for multiple rows then you should use the method :py:meth:`for_update()<Query.for_update>` of ``Query`` object.

.. py:method:: load()
load(args)

Loads all attributes which were not retrieved from the database yet. It loads lazy and non-lazy attributes, but not collection attributes. If an attribute was already loaded, it won't be loaded again. You can specify the list of attributes which needs to be loaded, or it's names. In this case Pony will load only them::

obj.load(Person.biography, Person.some_other_field)
obj.load('biography', 'some_other_field')

.. py:method:: select()
select(lambda)

Expand Down
50 changes: 45 additions & 5 deletions doc/working_with_relationships.txt
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,13 @@ You can treat a collection attribute as a regular Python collection and use stan

Returns the number of objects in the collection. If the collection is not loaded into cache, this methods loads all the collection instances into the cache first, and then returns the number of objects. Use this method if you are going to iterate over the objects and you need them loaded into the cache. If you don't need the collection to be loaded into the memory, you can use the :ref:`count() <set_count_ref>` method.

>>> p1 = Person[1]
>>> Car[1] in p1.cars
True
>>> len(p1.cars)
2
.. code-block:: python

>>> p1 = Person[1]
>>> Car[1] in p1.cars
True
>>> len(p1.cars)
2

Also there is a number of methods which you can call on a collection attribute.

Expand Down Expand Up @@ -288,6 +290,10 @@ Also there is a number of methods which you can call on a collection attribute.
new_tag = Tag(name='New tag')
Photo[123].tags.add(new_tag)

.. py:method:: load()

Loads all related objects from the database.


Collection class methods
------------------------------------
Expand Down Expand Up @@ -315,3 +321,37 @@ This method can be called on the entity class, not instance. For example::

Drops the intermediate table which is created for establishing many-to-many relationship. If the table is not empty and ``with_all_data=False``, the method raises the ``TableIsNotEmpty`` exception and doesn't delete anything. Setting the ``with_all_data=True`` allows you to delete the table even if it is not empty.


.. _col_queries_ref:

Collection queries
----------------------------

Starting with the release 0.6.1, Pony introduces queries for the relationship attributes.

You can apply :py:func:`select`, :py:meth:`Query.filter`, :py:meth:`Query.order_by`, :py:meth:`Query.page`, :py:meth:`Query.limit`, :py:meth:`Query.random` methods to the relationships to-many. The method names ``select`` and ``filter`` are synonyms.

Below you can find several examples of using these methods. We'll use the University schema for showing these queries, here are `python entity definitions <https://github.com/ponyorm/pony/blob/orm/pony/orm/examples/university1.py>`_ and `Entity-Relationship diagram <https://editor.ponyorm.com/user/pony/University>`_.

The example below selects all students with the ``gpa`` greater than 3 within the group 101::

g = Group[101]
g.students.filter(lambda student: student.gpa > 3)[:]

This query can be used for displaying the second page of group 101 student's list ordered by the ``name`` attribute::

g.students.order_by(Student.name).page(2, pagesize=3)

The same query can be also written in the following form::

g.students.order_by(lambda s: s.name).limit(3, offset=3)

The following query returns two random students from the group 101::

g.students.random(2)

And one more example. This query returns the first page of courses which were taken by ``Student[1]`` in the second semester, ordered by the course name::

s = Student[1]
s.courses.select(lambda c: c.semester == 2).order_by(Course.name).page(1)

2 changes: 1 addition & 1 deletion pony/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import sys
from os.path import dirname

__version__ = '0.6.1-dev'
__version__ = '0.6.1'

def detect_mode():
try: import google.appengine
Expand Down
2 changes: 1 addition & 1 deletion pony/converting.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def isbn13_to_isbn10(s):
# http://www.regular-expressions.info/email.html

email_re = re.compile(
r'^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|name|aero|biz|info|jobs|museum|coop)$',
r'^[a-z0-9._%+-]+@[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)+$',
re.IGNORECASE)

rfc2822_email_re = re.compile(r'''
Expand Down
5 changes: 3 additions & 2 deletions pony/orm/asttranslation.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ def postCallFunc(translator, node):

def create_extractors(code_key, tree, filter_num, globals, locals,
special_functions, const_functions, additional_internal_names=()):
result = extractors_cache.get(code_key)
cache_key = code_key, filter_num
result = extractors_cache.get(cache_key)
if result is None:
pretranslator = PreTranslator(
tree, globals, locals, special_functions, const_functions, additional_internal_names)
Expand All @@ -297,5 +298,5 @@ def create_extractors(code_key, tree, filter_num, globals, locals,
else: code = compile(src, src, 'eval')
extractors[filter_num, src] = code
varnames = list(sorted(extractors))
result = extractors_cache[code_key] = extractors, varnames, tree
result = extractors_cache[cache_key] = extractors, varnames, tree
return result
Loading

0 comments on commit 5282b2d

Please sign in to comment.