Skip to content

Commit

Permalink
Pony ORM release 0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
kozlovsky committed May 31, 2014
2 parents 386f963 + e582b11 commit 9ee610d
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 57 deletions.
57 changes: 57 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Pony ORM Release 0.5 (2014-05-31)

## Changes since 0.4.9

* New transaction model ([link](http://blog.ponyorm.com/?p=125))
* New method `Query.filter()` allows step-by-step query construction ([link](http://doc.ponyorm.com/queries.html?highlight=filter#Query.filter))
* New method `Database.bind()` simplifies testing and allows using different settings for development and production ([link](http://doc.ponyorm.com/database.html#binding-the-database-object-to-a-specific-database))
* New method `Query.page()` simplifies pagination ([link](http://doc.ponyorm.com/queries.html?highlight=filter#Query.page))
* New method `MyEntity.select_random(N)` is effective for large tables ([link](http://doc.ponyorm.com/queries.html#Entity.select_random))
* New method `Query.random(N)` for selecting random instances ([link](http://doc.ponyorm.com/queries.html#Query.random))
* Support of new `concat()` function inside declarative queries
* New `before_insert()`, `before_update()`, `before_delete()` entity instance hooks which can be overridden
* Ability to specify `sequence_name='seq_name'` for PrimaryKey attributes for Oracle database
* Ability to create new entity instances specifying the value of the primary key instead of the object
* Ability to read entity object attributes outside of the db_session
* Ability to use lambdas as a reference to an entity in relationship attribute declarations ([link](http://doc.ponyorm.com/entities.html?highlight=lambda#relationships))
* The names of tables, indexes and constraints in the database creation script now are sorted in the alphabetical order
* In MySQL and PostgreSQL Pony converts the table names to the lower case. In Oracle – to the upper case. In SQLite leaves as is.
* The option `options.MAX_FETCH_COUNT` is set to `None` by default now
* The support of PyGreSQL is discontinued, using psycopg2 instead
* Added `pony.__version__` attribute
* Multiple bugs were fixed
* Stability and performance improvements


# Pony ORM Release 0.4.9 (2013-10-25)

* Database `create_tables()`/`drop_all_tables()` methods
* `Database.drop_table(name)`, `Entity.drop_table()`, `Set.drop_table()` methods
* `Database.disconnect()` methods (allows SQLite files deletion after disconnection)
* Pony now automatically enables foreign key checks in SQLite
* `Entity.exists(...)` method added
* `distinct()` function added: `select((s.group, sum(distinct(s.gpa))) for s in Student)`
* Refactoring & bugfixes


# Pony ORM Release 0.4.8 (2013-08-27)

* Use standard transaction mode by default instead of optimistic mode
* `SELECT ... FOR UPDATE` support added: `select(...).for_update()[:]`
* `UUID` datatype support added
* Automatic foreign key indexes generation
* MySQL foreign key bug workaround added
* Check_tables parameter of `generate_mapping()` is deprecated
* Bug fixes


# Pony ORM Release 0.4.7 (2013-06-19)

* `@db_session` decorator is required for any database interaction;
* support of pickling/unpickling (queries and objects can be stored in memcached);
* lazy collections - don't load all the items if only one is needed;
* datetime precision now can be specified;
* multiple bugs were fixed.


# Pony ORM Release 0.4.6 (2013-05-17)
6 changes: 3 additions & 3 deletions doc/aggregations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ or::

select((s.group, count(s)) for s in Student if s.group.dept.number == 44)

.. note:: Either of the listed queries will provide the same result, but Pony translated them differently in SQL. If, as in the first request, aggregative function includes a collection, then Pony will translate it into a subquery. In the second case, when the aggregative function includes a single object instead of a collection, a subquery will not be created, but rather grouping will be used in the main query. In many database systems, subqueries process longer compared to queries with grouping, thus the second option of query creation is preferred.
In the first example the aggregate function ``count`` receives a collection and Pony will translate it into a subquery (although Pony will try to optimize the query and replace it with ``LEFT JOIN``).

So, for a fast query, the "smallest" object type from the query should be used for the "for" cycle, while all other objects should be taken through the chain of attributes. In this case, although we want to receive groups in an answer, the student is the "smallest" object that should be taken into an account, and thus the cycle should be done for the student, and the group will be taken as an attribute of the student.
In the second example, the function ``count`` receives a single object instead of a collection. In this case Pony will add a ``GROUP BY`` section to the SQL query and the grouping will be done on the ``s.group`` attribute.

.. note:: There are two types of COUNT function in SQL: COUNT (column) and COUNT (DISTINCT column). If a column is not a primary key, then in majority of the cases we will want to use the COUNT (DISTINCT column) type, as the type without DISTINCT counts duplicate values several times, which means that it basically ignores the true content of a column and is simply calculating the amount of cells in a table with value other than NULL. This often leads to errors in query creation in SQL. Pony introduces DISTINCT automatically, if it understands that the column might include duplicate values; therefore Pony only has one function COUNT.
If you use the ``count()`` function without arguments, this will be translated to ``COUNT(*)``. If you specify an argument, it will be translated to ``COUNT(DISTINCT column)``


Conditional COUNT
Expand Down
83 changes: 68 additions & 15 deletions doc/collections.txt
Original file line number Diff line number Diff line change
@@ -1,55 +1,108 @@
Collections (to-many relationships)
======================================

When you need to define one-to-many or many-to-many relationship, you should use a ``Set`` attribute which represents a collection::

class User(db.Entity):
name = Required(unicode)
photos = Set('Photo')

Collection declaration
------------------------------
class Photo(db.Entity):
content = Required(buffer)
user = Required(User)
tags = Set('Tag')

.. class:: Set
class Tag(db.Entity):
name = PrimaryKey(unicode)
photos = Set(Photo)

During the declaration of ``Set`` attribute of an entity you can specify the following options:
In the example above we've defined one-to-many relationship between User and Photo and many-to-many relationship between Photo and Tag entities. Below you can see the description of additional parameters which can be passed during the declaration of relationship attributes.

.. py:attribute:: nplus1_threshold
Collection attributes parameters
-----------------------------------------

.. py:attribute:: table

For many-to-many relationships only
.. class:: Set

.. py:attribute:: symmetric
Represents the to-many relationship.

.. py:attribute:: lazy

.. py:attribute:: column/columns
When we access a specific collection item (check if an element belongs to a collection, add or delete items), Pony loads the whole collection to the db_session cache. Usually it increases the performance reducing the database round trips. But if you have large collections you may prefer not to load them into the cache. Setting ``lazy=True`` tells Pony that it shouldn't load the collection to the cache, but always send queries to the database. Default is ``lazy=False``.

.. py:attribute:: reverse

.. py:attribute:: reverse_column
Specifies the name of the attribute of related entity which is used for the relationship. This parameter should be used when there are more than one relationship between two entities.

.. py:attribute:: table

This parameter is used for many-to-many relationships only and allows to specify the name of the intermediate table used for representing this relationship in the database.

.. py:attribute:: column
columns
reverse_column
reverse_columns

.. py:attribute:: reverse_columns
These parameters are used for many-to-many relationships and allows to specify the name of the intermediate columns. The ``columns`` and ``reverse_columns`` parameters receive a list and used when the entity has a composite key. Typically you use the ``column`` or ``columns`` parameters in both relationship attributes if you don't like the default column name.

.. py:attribute:: cascade_delete

Boolean value which controls the cascade deletion of the related objects. Default value depends on the another side of the relationship. If it is ``Optional`` - the default value is ``False`` and if it is ``Required`` then ``True``.

.. py:attribute:: nplus1_threshold

This parameter is used for fine tuning of the N+1 problem solution.


Collection instance methods
------------------------------------

.. class:: Set

.. py:method:: add(item)
add(iter)

Adding instances to a collection establishes a two-way relationship between entity instances::

photo = Photo[123]
photo.tags.add(Tag['Outdoors'])

Now the instance of the ``Photo`` entity with the primary key 123 has a relationship with the ``Tag['Outdoors']`` instance. The attribute ``photos`` of the ``Tag['Outdoors']`` instance contains the reference to the ``Photo[123]`` as well.

We can also establish several relationships at once passing the list of tags to the ``add()`` method::

photo.tags.add([Tag['Party'], Tag['New Year']])

.. py:method:: remove(item)
remove(iter)

Remove an item or items from the collection and thus break the relationship between entity instances.

.. py:method:: clear()

Remove all items from the collection which means breaking relationships between entity instances.

.. py:method:: is_empty()

Returns ``False`` if there is at lease one relationship and ``True`` if this attribute has no relationships.

.. py:method:: copy()

Returns a Python ``set`` object which contains the same items as the given collection.

.. py:method:: count()

Returns the amount of objects in the collection.

.. py:method:: create(**kwargs)

.. py:method:: is_empty()
Create an return an instance of the related entity and establish a relationship with it::

.. py:method:: remove(item)
remove(iter)
new_tag = Photo[123].tags.create(name='New tag')

is an equivalent of the following::

new_tag = Tag(name='New tag')
Photo[123].tags.add(new_tag)


Attribute lifting
Expand Down
4 changes: 4 additions & 0 deletions doc/crud.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ or in a line, using the ``set()`` method::
order = Order[123]
order.set(state = "Shipped", date_shipped = datetime.now())

The ``set()`` method can be convenient when you need to update several object attributes at once from a dictionary::

order.set(**dict_with_new_values)

In the future, Pony will be augmented with an option to perform a bulk update (updating multiple objects on the disk without loading them to the cache)::

update(p.set(price=price * 1.1) for p in Product
Expand Down
Loading

0 comments on commit 9ee610d

Please sign in to comment.