~ubuntu-branches/debian/jessie/sqlalchemy/jessie

« back to all changes in this revision

Viewing changes to doc/_sources/changelog/migration_05.txt

  • Committer: Package Import Robot
  • Author(s): Piotr Ożarowski, Jakub Wilk, Piotr Ożarowski
  • Date: 2013-07-06 20:53:52 UTC
  • mfrom: (1.4.23) (16.1.17 experimental)
  • Revision ID: package-import@ubuntu.com-20130706205352-ryppl1eto3illd79
Tags: 0.8.2-1
[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Piotr Ożarowski ]
* New upstream release
* Upload to unstable
* Build depend on python3-all instead of -dev, extensions are not built for
  Python 3.X 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
=============================
 
2
What's new in SQLAlchemy 0.5?
 
3
=============================
 
4
 
 
5
.. admonition:: About this Document
 
6
 
 
7
    This document describes changes between SQLAlchemy version 0.4,
 
8
    last released October 12, 2008, and SQLAlchemy version 0.5,
 
9
    last released January 16, 2010.
 
10
 
 
11
    Document date: August 4, 2009
 
12
 
 
13
 
 
14
This guide documents API changes which affect users
 
15
migrating their applications from the 0.4 series of
 
16
SQLAlchemy to 0.5.   It's also recommended for those working
 
17
from  `Essential SQLAlchemy
 
18
<http://oreilly.com/catalog/9780596516147/>`_, which only
 
19
covers 0.4 and seems to even have some old 0.3isms in it.
 
20
Note that SQLAlchemy 0.5 removes many behaviors which were
 
21
deprecated throughout the span of the 0.4 series, and also
 
22
deprecates more behaviors specific to 0.4.
 
23
 
 
24
Major Documentation Changes
 
25
===========================
 
26
 
 
27
Some sections of the documentation have been completely
 
28
rewritten and can serve as an introduction to new ORM
 
29
features.  The ``Query`` and ``Session`` objects in
 
30
particular have some distinct differences in API and
 
31
behavior which fundamentally change many of the basic ways
 
32
things are done, particularly with regards to constructing
 
33
highly customized ORM queries and dealing with stale session
 
34
state, commits and rollbacks.
 
35
 
 
36
* `ORM Tutorial
 
37
  <http://www.sqlalchemy.org/docs/05/ormtutorial.html>`_
 
38
 
 
39
* `Session Documentation
 
40
  <http://www.sqlalchemy.org/docs/05/session.html>`_
 
41
 
 
42
Deprecations Source
 
43
===================
 
44
 
 
45
Another source of information is documented within a series
 
46
of unit tests illustrating up to date usages of some common
 
47
``Query`` patterns; this file can be viewed at
 
48
[source:sqlalchemy/trunk/test/orm/test_deprecations.py].
 
49
 
 
50
Requirements Changes
 
51
====================
 
52
 
 
53
* Python 2.4 or higher is required.  The SQLAlchemy 0.4 line
 
54
  is the last version with Python 2.3 support.
 
55
 
 
56
Object Relational Mapping
 
57
=========================
 
58
 
 
59
* **Column level expressions within Query.** - as detailed
 
60
  in the `tutorial
 
61
  <http://www.sqlalchemy.org/docs/05/ormtutorial.html>`_,
 
62
  ``Query`` has the capability to create specific SELECT
 
63
  statements, not just those against full rows:
 
64
 
 
65
  ::
 
66
 
 
67
      session.query(User.name, func.count(Address.id).label("numaddresses")).join(Address).group_by(User.name)
 
68
 
 
69
  The tuples returned by any multi-column/entity query are
 
70
  *named*' tuples:
 
71
 
 
72
  ::
 
73
 
 
74
      for row in session.query(User.name, func.count(Address.id).label('numaddresses')).join(Address).group_by(User.name):
 
75
         print "name", row.name, "number", row.numaddresses
 
76
 
 
77
  ``Query`` has a ``statement`` accessor, as well as a
 
78
  ``subquery()`` method which allow ``Query`` to be used to
 
79
  create more complex combinations:
 
80
 
 
81
  ::
 
82
 
 
83
      subq = session.query(Keyword.id.label('keyword_id')).filter(Keyword.name.in_(['beans', 'carrots'])).subquery()
 
84
      recipes = session.query(Recipe).filter(exists().
 
85
         where(Recipe.id==recipe_keywords.c.recipe_id).
 
86
         where(recipe_keywords.c.keyword_id==subq.c.keyword_id)
 
87
      )
 
88
 
 
89
* **Explicit ORM aliases are recommended for aliased joins**
 
90
  - The ``aliased()`` function produces an "alias" of a
 
91
  class, which allows fine-grained control of aliases in
 
92
  conjunction with ORM queries.  While a table-level alias
 
93
  (i.e. ``table.alias()``) is still usable, an ORM level
 
94
  alias retains the semantics of the ORM mapped object which
 
95
  is significant for inheritance mappings, options, and
 
96
  other scenarios.  E.g.:
 
97
 
 
98
  ::
 
99
 
 
100
      Friend = aliased(Person)
 
101
      session.query(Person, Friend).join((Friend, Person.friends)).all()
 
102
 
 
103
* **query.join() greatly enhanced.** - You can now specify
 
104
  the target and ON clause for a join in multiple ways.   A
 
105
  target class alone can be provided where SQLA will attempt
 
106
  to form a join to it via foreign key in the same way as
 
107
  ``table.join(someothertable)``.  A target and an explicit
 
108
  ON condition can be provided, where the ON condition can
 
109
  be a ``relation()`` name, an actual class descriptor, or a
 
110
  SQL expression.  Or the old way of just a ``relation()``
 
111
  name or class descriptor works too.   See the ORM tutorial
 
112
  which has several examples.
 
113
 
 
114
* **Declarative is recommended for applications which don't
 
115
  require (and don't prefer) abstraction between tables and
 
116
  mappers** - The [/docs/05/reference/ext/declarative.html
 
117
  Declarative] module, which is used to combine the
 
118
  expression of ``Table``, ``mapper()``, and user defined
 
119
  class objects together, is highly recommended as it
 
120
  simplifies application configuration, ensures the "one
 
121
  mapper per class" pattern, and allows the full range of
 
122
  configuration available to distinct ``mapper()`` calls.
 
123
  Separate ``mapper()`` and ``Table`` usage is now referred
 
124
  to as "classical SQLAlchemy usage" and of course is freely
 
125
  mixable with declarative.
 
126
 
 
127
* **The .c. attribute has been removed** from classes (i.e.
 
128
  ``MyClass.c.somecolumn``).  As is the case in 0.4, class-
 
129
  level properties are usable as query elements, i.e.
 
130
  ``Class.c.propname`` is now superseded by
 
131
  ``Class.propname``, and the ``c`` attribute continues to
 
132
  remain on ``Table`` objects where they indicate the
 
133
  namespace of ``Column`` objects present on the table.
 
134
 
 
135
  To get at the Table for a mapped class (if you didn't keep
 
136
  it around already):
 
137
 
 
138
  ::
 
139
 
 
140
      table = class_mapper(someclass).mapped_table
 
141
 
 
142
  Iterate through columns:
 
143
 
 
144
  ::
 
145
 
 
146
      for col in table.c:
 
147
          print col
 
148
 
 
149
  Work with a specific column:
 
150
 
 
151
  ::
 
152
 
 
153
      table.c.somecolumn
 
154
 
 
155
  The class-bound descriptors support the full set of Column
 
156
  operators as well as the documented relation-oriented
 
157
  operators like ``has()``, ``any()``, ``contains()``, etc.
 
158
 
 
159
  The reason for the hard removal of ``.c.`` is that in 0.5,
 
160
  class-bound descriptors carry potentially different
 
161
  meaning, as well as information regarding class mappings,
 
162
  versus plain ``Column`` objects - and there are use cases
 
163
  where you'd specifically want to use one or the other.
 
164
  Generally, using class-bound descriptors invokes a set of
 
165
  mapping/polymorphic aware translations, and using table-
 
166
  bound columns does not.  In 0.4, these translations were
 
167
  applied across the board to all expressions, but 0.5
 
168
  differentiates completely between columns and mapped
 
169
  descriptors, only applying translations to the latter.  So
 
170
  in many cases, particularly when dealing with joined table
 
171
  inheritance configurations as well as when using
 
172
  ``query(<columns>)``, ``Class.propname`` and
 
173
  ``table.c.colname`` are not interchangeable.
 
174
 
 
175
  For example, ``session.query(users.c.id, users.c.name)``
 
176
  is different versus ``session.query(User.id, User.name)``;
 
177
  in the latter case, the ``Query`` is aware of the mapper
 
178
  in use and further mapper-specific operations like
 
179
  ``query.join(<propname>)``, ``query.with_parent()`` etc.
 
180
  may be used, but in the former case cannot.  Additionally,
 
181
  in polymorphic inheritance scenarios, the class-bound
 
182
  descriptors refer to the columns present in the
 
183
  polymorphic selectable in use, not necessarily the table
 
184
  column which directly corresponds to the descriptor.  For
 
185
  example, a set of classes related by joined-table
 
186
  inheritance to the ``person`` table along the
 
187
  ``person_id`` column of each table will all have their
 
188
  ``Class.person_id`` attribute mapped to the ``person_id``
 
189
  column in ``person``, and not their subclass table.
 
190
  Version 0.4 would map this behavior onto table-bound
 
191
  ``Column`` objects automatically.  In 0.5, this automatic
 
192
  conversion has been removed, so that you in fact *can* use
 
193
  table-bound columns as a means to override the
 
194
  translations which occur with polymorphic querying; this
 
195
  allows ``Query`` to be able to create optimized selects
 
196
  among joined-table or concrete-table inheritance setups,
 
197
  as well as portable subqueries, etc.
 
198
 
 
199
* **Session Now Synchronizes Automatically with
 
200
  Transactions.** Session now synchronizes against the
 
201
  transaction automatically by default, including autoflush
 
202
  and autoexpire.  A transaction is present at all times
 
203
  unless disabled using the ``autocommit`` option.  When all
 
204
  three flags are set to their default, the Session recovers
 
205
  gracefully after rollbacks and it's very difficult to get
 
206
  stale data into the session.  See the new Session
 
207
  documentation for details.
 
208
 
 
209
* **Implicit Order By Is Removed**.  This will impact ORM
 
210
  users who rely upon SA's "implicit ordering" behavior,
 
211
  which states that all Query objects which don't have an
 
212
  ``order_by()`` will ORDER BY the "id" or "oid" column of
 
213
  the primary mapped table, and all lazy/eagerly loaded
 
214
  collections apply a similar ordering.   In 0.5, automatic
 
215
  ordering must be explicitly configured on ``mapper()`` and
 
216
  ``relation()`` objects (if desired), or otherwise when
 
217
  using ``Query``.
 
218
 
 
219
  To convert an 0.4 mapping to 0.5, such that its ordering
 
220
  behavior will be extremely similar to 0.4 or previous, use
 
221
  the ``order_by`` setting on ``mapper()`` and
 
222
  ``relation()``:
 
223
 
 
224
  ::
 
225
 
 
226
          mapper(User, users, properties={
 
227
              'addresses':relation(Address, order_by=addresses.c.id)
 
228
          }, order_by=users.c.id)
 
229
 
 
230
  To set ordering on a backref, use the ``backref()``
 
231
  function:
 
232
 
 
233
  ::
 
234
 
 
235
          'keywords':relation(Keyword, secondary=item_keywords,
 
236
                order_by=keywords.c.name, backref=backref('items', order_by=items.c.id))
 
237
 
 
238
  Using declarative ?  To help with the new ``order_by``
 
239
  requirement, ``order_by`` and friends can now be set using
 
240
  strings which are evaluated in Python later on (this works
 
241
  **only** with declarative, not plain mappers):
 
242
 
 
243
  ::
 
244
 
 
245
          class MyClass(MyDeclarativeBase):
 
246
              ...
 
247
              'addresses':relation("Address", order_by="Address.id")
 
248
 
 
249
  It's generally a good idea to set ``order_by`` on
 
250
  ``relation()s`` which load list-based collections of
 
251
  items, since that ordering cannot otherwise be affected.
 
252
  Other than that, the best practice is to use
 
253
  ``Query.order_by()`` to control ordering of the primary
 
254
  entities being loaded.
 
255
 
 
256
* **Session is now
 
257
  autoflush=True/autoexpire=True/autocommit=False.** - To
 
258
  set it up, just call ``sessionmaker()`` with no arguments.
 
259
  The name ``transactional=True`` is now
 
260
  ``autocommit=False``.  Flushes occur upon each query
 
261
  issued (disable with ``autoflush=False``), within each
 
262
  ``commit()`` (as always), and before each
 
263
  ``begin_nested()`` (so rolling back to the SAVEPOINT is
 
264
  meaningful).   All objects are expired after each
 
265
  ``commit()`` and after each ``rollback()``.  After
 
266
  rollback, pending objects are expunged, deleted objects
 
267
  move back to persistent.  These defaults work together
 
268
  very nicely and there's really no more need for old
 
269
  techniques like ``clear()`` (which is renamed to
 
270
  ``expunge_all()`` as well).
 
271
 
 
272
  P.S.:  sessions are now reusable after a ``rollback()``.
 
273
  Scalar and collection attribute changes, adds and deletes
 
274
  are all rolled back.
 
275
 
 
276
* **session.add() replaces session.save(), session.update(),
 
277
  session.save_or_update().** - the
 
278
  ``session.add(someitem)`` and ``session.add_all([list of
 
279
  items])`` methods replace ``save()``, ``update()``, and
 
280
  ``save_or_update()``.  Those methods will remain
 
281
  deprecated throughout 0.5.
 
282
 
 
283
* **backref configuration made less verbose.** - The
 
284
  ``backref()`` function now uses the ``primaryjoin`` and
 
285
  ``secondaryjoin`` arguments of the forwards-facing
 
286
  ``relation()`` when they are not explicitly stated.  It's
 
287
  no longer necessary to specify
 
288
  ``primaryjoin``/``secondaryjoin`` in both directions
 
289
  separately.
 
290
 
 
291
* **Simplified polymorphic options.** - The ORM's
 
292
  "polymorphic load" behavior has been simplified.  In 0.4,
 
293
  mapper() had an argument called ``polymorphic_fetch``
 
294
  which could be configured as ``select`` or ``deferred``.
 
295
  This option is removed; the mapper will now just defer any
 
296
  columns which were not present in the SELECT statement.
 
297
  The actual SELECT statement used is controlled by the
 
298
  ``with_polymorphic`` mapper argument (which is also in 0.4
 
299
  and replaces ``select_table``), as well as the
 
300
  ``with_polymorphic()`` method on ``Query`` (also in 0.4).
 
301
 
 
302
  An improvement to the deferred loading of inheriting
 
303
  classes is that the mapper now produces the "optimized"
 
304
  version of the SELECT statement in all cases; that is, if
 
305
  class B inherits from A, and several attributes only
 
306
  present on class B have been expired, the refresh
 
307
  operation will only include B's table in the SELECT
 
308
  statement and will not JOIN to A.
 
309
 
 
310
* The ``execute()`` method on ``Session`` converts plain
 
311
  strings into ``text()`` constructs, so that bind
 
312
  parameters may all be specified as ":bindname" without
 
313
  needing to call ``text()`` explicitly.  If "raw" SQL is
 
314
  desired here, use ``session.connection().execute("raw
 
315
  text")``.
 
316
 
 
317
* ``session.Query().iterate_instances()`` has been renamed
 
318
  to just ``instances()``. The old ``instances()`` method
 
319
  returning a list instead of an iterator no longer exists.
 
320
  If you were relying on that behavior, you should use
 
321
  ``list(your_query.instances())``.
 
322
 
 
323
Extending the ORM
 
324
=================
 
325
 
 
326
In 0.5 we're moving forward with more ways to modify and
 
327
extend the ORM.  Heres a summary:
 
328
 
 
329
* **MapperExtension.** - This is the classic extension
 
330
  class, which remains.   Methods which should rarely be
 
331
  needed are ``create_instance()`` and
 
332
  ``populate_instance()``.  To control the initialization of
 
333
  an object when it's loaded from the database, use the
 
334
  ``reconstruct_instance()`` method, or more easily the
 
335
  ``@reconstructor`` decorator described in the
 
336
  documentation.
 
337
 
 
338
* **SessionExtension.** - This is an easy to use extension
 
339
  class for session events.  In particular, it provides
 
340
  ``before_flush()``, ``after_flush()`` and
 
341
  ``after_flush_postexec()`` methods.  It's usage is
 
342
  recommended over ``MapperExtension.before_XXX`` in many
 
343
  cases since within ``before_flush()`` you can modify the
 
344
  flush plan of the session freely, something which cannot
 
345
  be done from within ``MapperExtension``.
 
346
 
 
347
* **AttributeExtension.** - This class is now part of the
 
348
  public API, and allows the interception of userland events
 
349
  on attributes, including attribute set and delete
 
350
  operations, and collection appends and removes.  It also
 
351
  allows the value to be set or appended to be modified.
 
352
  The ``@validates`` decorator, described in the
 
353
  documentation, provides a quick way to mark any mapped
 
354
  attributes as being "validated" by a particular class
 
355
  method.
 
356
 
 
357
* **Attribute Instrumentation Customization.** - An API is
 
358
  provided for ambitious efforts to entirely replace
 
359
  SQLAlchemy's attribute instrumentation, or just to augment
 
360
  it in some cases.  This API was produced for the purposes
 
361
  of the Trellis toolkit, but is available as a public API.
 
362
  Some examples are provided in the distribution in the
 
363
  ``/examples/custom_attributes`` directory.
 
364
 
 
365
Schema/Types
 
366
============
 
367
 
 
368
* **String with no length no longer generates TEXT, it
 
369
  generates VARCHAR** - The ``String`` type no longer
 
370
  magically converts into a ``Text`` type when specified
 
371
  with no length.  This only has an effect when CREATE TABLE
 
372
  is issued, as it will issue ``VARCHAR`` with no length
 
373
  parameter, which is not valid on many (but not all)
 
374
  databases.  To create a TEXT (or CLOB, i.e. unbounded
 
375
  string) column, use the ``Text`` type.
 
376
 
 
377
* **PickleType() with mutable=True requires an __eq__()
 
378
  method** - The ``PickleType`` type needs to compare values
 
379
  when mutable=True.  The method of comparing
 
380
  ``pickle.dumps()`` is inefficient and unreliable.  If an
 
381
  incoming object does not implement ``__eq__()`` and is
 
382
  also not ``None``, the ``dumps()`` comparison is used but
 
383
  a warning is raised.  For types which implement
 
384
  ``__eq__()`` which includes all dictionaries, lists, etc.,
 
385
  comparison will use ``==`` and is now reliable by default.
 
386
 
 
387
* **convert_bind_param() and convert_result_value() methods
 
388
  of TypeEngine/TypeDecorator are removed.** - The O'Reilly
 
389
  book unfortunately documented these methods even though
 
390
  they were deprecated post 0.3.   For a user-defined type
 
391
  which subclasses ``TypeEngine``, the ``bind_processor()``
 
392
  and ``result_processor()`` methods should be used for
 
393
  bind/result processing.  Any user defined type, whether
 
394
  extending ``TypeEngine`` or ``TypeDecorator``, which uses
 
395
  the old 0.3 style can be easily adapted to the new style
 
396
  using the following adapter:
 
397
 
 
398
  ::
 
399
 
 
400
      class AdaptOldConvertMethods(object):
 
401
          """A mixin which adapts 0.3-style convert_bind_param and
 
402
          convert_result_value methods
 
403
 
 
404
          """
 
405
          def bind_processor(self, dialect):
 
406
              def convert(value):
 
407
                  return self.convert_bind_param(value, dialect)
 
408
              return convert
 
409
 
 
410
          def result_processor(self, dialect):
 
411
              def convert(value):
 
412
                  return self.convert_result_value(value, dialect)
 
413
              return convert
 
414
 
 
415
          def convert_result_value(self, value, dialect):
 
416
              return value
 
417
 
 
418
          def convert_bind_param(self, value, dialect):
 
419
              return value
 
420
 
 
421
  To use the above mixin:
 
422
 
 
423
  ::
 
424
 
 
425
      class MyType(AdaptOldConvertMethods, TypeEngine):
 
426
         # ...
 
427
 
 
428
* The ``quote`` flag on ``Column`` and ``Table`` as well as
 
429
  the ``quote_schema`` flag on ``Table`` now control quoting
 
430
  both positively and negatively.  The default is ``None``,
 
431
  meaning let regular quoting rules take effect. When
 
432
  ``True``, quoting is forced on.  When ``False``, quoting
 
433
  is forced off.
 
434
 
 
435
* Column ``DEFAULT`` value DDL can now be more conveniently
 
436
  specified with ``Column(..., server_default='val')``,
 
437
  deprecating ``Column(..., PassiveDefault('val'))``.
 
438
  ``default=`` is now exclusively for Python-initiated
 
439
  default values, and can coexist with server_default.  A
 
440
  new ``server_default=FetchedValue()`` replaces the
 
441
  ``PassiveDefault('')`` idiom for marking columns as
 
442
  subject to influence from external triggers and has no DDL
 
443
  side effects.
 
444
 
 
445
* SQLite's ``DateTime``, ``Time`` and ``Date`` types now
 
446
  **only accept datetime objects, not strings** as bind
 
447
  parameter input.  If you'd like to create your own
 
448
  "hybrid" type which accepts strings and returns results as
 
449
  date objects (from whatever format you'd like), create a
 
450
  ``TypeDecorator`` that builds on ``String``.  If you only
 
451
  want string-based dates, just use ``String``.
 
452
 
 
453
* Additionally, the ``DateTime`` and ``Time`` types, when
 
454
  used with SQLite, now represent the "microseconds" field
 
455
  of the Python ``datetime.datetime`` object in the same
 
456
  manner as ``str(datetime)`` - as fractional seconds, not a
 
457
  count of microseconds.  That is:
 
458
 
 
459
  ::
 
460
 
 
461
       dt = datetime.datetime(2008, 6, 27, 12, 0, 0, 125)  # 125 usec
 
462
 
 
463
       # old way
 
464
       '2008-06-27 12:00:00.125'
 
465
 
 
466
       # new way
 
467
       '2008-06-27 12:00:00.000125'
 
468
 
 
469
  So if an existing SQLite file-based database intends to be
 
470
  used across 0.4 and 0.5, you either have to upgrade the
 
471
  datetime columns to store the new format (NOTE: please
 
472
  test this, I'm pretty sure its correct):
 
473
 
 
474
  ::
 
475
 
 
476
       UPDATE mytable SET somedatecol =
 
477
         substr(somedatecol, 0, 19) || '.' || substr((substr(somedatecol, 21, -1) / 1000000), 3, -1);
 
478
 
 
479
  or, enable "legacy" mode as follows:
 
480
 
 
481
  ::
 
482
 
 
483
       from sqlalchemy.databases.sqlite import DateTimeMixin
 
484
       DateTimeMixin.__legacy_microseconds__ = True
 
485
 
 
486
Connection Pool no longer threadlocal by default
 
487
================================================
 
488
 
 
489
0.4 has an unfortunate default setting of
 
490
"pool_threadlocal=True", leading to surprise behavior when,
 
491
for example, using multiple Sessions within a single thread.
 
492
This flag is now off in 0.5.   To re-enable 0.4's behavior,
 
493
specify ``pool_threadlocal=True`` to ``create_engine()``, or
 
494
alternatively use the "threadlocal" strategy via
 
495
``strategy="threadlocal"``.
 
496
 
 
497
\*args Accepted, \*args No Longer Accepted
 
498
==========================================
 
499
 
 
500
The policy with ``method(\*args)`` vs. ``method([args])``
 
501
is, if the method accepts a variable-length set of items
 
502
which represent a fixed structure, it takes ``\*args``.  If
 
503
the method accepts a variable-length set of items that are
 
504
data-driven, it takes ``[args]``.
 
505
 
 
506
* The various Query.options() functions ``eagerload()``,
 
507
  ``eagerload_all()``, ``lazyload()``, ``contains_eager()``,
 
508
  ``defer()``, ``undefer()`` all accept variable-length
 
509
  ``\*keys`` as their argument now, which allows a path to
 
510
  be formulated using descriptors, ie.:
 
511
 
 
512
  ::
 
513
 
 
514
         query.options(eagerload_all(User.orders, Order.items, Item.keywords))
 
515
 
 
516
  A single array argument is still accepted for backwards
 
517
  compatibility.
 
518
 
 
519
* Similarly, the ``Query.join()`` and ``Query.outerjoin()``
 
520
  methods accept a variable length \*args, with a single
 
521
  array accepted for backwards compatibility:
 
522
 
 
523
  ::
 
524
 
 
525
         query.join('orders', 'items')
 
526
         query.join(User.orders, Order.items)
 
527
 
 
528
* the ``in_()`` method on columns and similar only accepts a
 
529
  list argument now.  It no longer accepts ``\*args``.
 
530
 
 
531
Removed
 
532
=======
 
533
 
 
534
* **entity_name** - This feature was always problematic and
 
535
  rarely used.  0.5's more deeply fleshed out use cases
 
536
  revealed further issues with ``entity_name`` which led to
 
537
  its removal.  If different mappings are required for a
 
538
  single class, break the class into separate subclasses and
 
539
  map them separately.  An example of this is at
 
540
  [wiki:UsageRecipes/EntityName].  More information
 
541
  regarding rationale is described at http://groups.google.c
 
542
  om/group/sqlalchemy/browse_thread/thread/9e23a0641a88b96d?
 
543
  hl=en .
 
544
 
 
545
* **get()/load() cleanup**
 
546
 
 
547
 
 
548
  The ``load()`` method has been removed.  It's
 
549
  functionality was kind of arbitrary and basically copied
 
550
  from Hibernate, where it's also not a particularly
 
551
  meaningful method.
 
552
 
 
553
  To get equivalent functionality:
 
554
 
 
555
  ::
 
556
 
 
557
       x = session.query(SomeClass).populate_existing().get(7)
 
558
 
 
559
  ``Session.get(cls, id)`` and ``Session.load(cls, id)``
 
560
  have been removed.  ``Session.get()`` is redundant vs.
 
561
  ``session.query(cls).get(id)``.
 
562
 
 
563
  ``MapperExtension.get()`` is also removed (as is
 
564
  ``MapperExtension.load()``).  To override the
 
565
  functionality of ``Query.get()``, use a subclass:
 
566
 
 
567
  ::
 
568
 
 
569
       class MyQuery(Query):
 
570
           def get(self, ident):
 
571
               # ...
 
572
 
 
573
       session = sessionmaker(query_cls=MyQuery)()
 
574
 
 
575
       ad1 = session.query(Address).get(1)
 
576
 
 
577
* ``sqlalchemy.orm.relation()``
 
578
 
 
579
 
 
580
  The following deprecated keyword arguments have been
 
581
  removed:
 
582
 
 
583
  foreignkey, association, private, attributeext, is_backref
 
584
 
 
585
  In particular, ``attributeext`` is replaced with
 
586
  ``extension`` - the ``AttributeExtension`` class is now in
 
587
  the public API.
 
588
 
 
589
* ``session.Query()``
 
590
 
 
591
 
 
592
  The following deprecated functions have been removed:
 
593
 
 
594
  list, scalar, count_by, select_whereclause, get_by,
 
595
  select_by, join_by, selectfirst, selectone, select,
 
596
  execute, select_statement, select_text, join_to, join_via,
 
597
  selectfirst_by, selectone_by, apply_max, apply_min,
 
598
  apply_avg, apply_sum
 
599
 
 
600
  Additionally, the ``id`` keyword argument to ``join()``,
 
601
  ``outerjoin()``, ``add_entity()`` and ``add_column()`` has
 
602
  been removed.  To target table aliases in ``Query`` to
 
603
  result columns, use the ``aliased`` construct:
 
604
 
 
605
  ::
 
606
 
 
607
      from sqlalchemy.orm import aliased
 
608
      address_alias = aliased(Address)
 
609
      print session.query(User, address_alias).join((address_alias, User.addresses)).all()
 
610
 
 
611
* ``sqlalchemy.orm.Mapper``
 
612
 
 
613
 
 
614
  * instances()
 
615
 
 
616
 
 
617
  * get_session() - this method was not very noticeable, but
 
618
    had the effect of associating lazy loads with a
 
619
    particular session even if the parent object was
 
620
    entirely detached, when an extension such as
 
621
    ``scoped_session()`` or the old ``SessionContextExt``
 
622
    was used.  It's possible that some applications which
 
623
    relied upon this behavior will no longer work as
 
624
    expected;  but the better programming practice here is
 
625
    to always ensure objects are present within sessions if
 
626
    database access from their attributes are required.
 
627
 
 
628
* ``mapper(MyClass, mytable)``
 
629
 
 
630
 
 
631
  Mapped classes no are longer instrumented with a "c" class
 
632
  attribute; e.g. ``MyClass.c``
 
633
 
 
634
* ``sqlalchemy.orm.collections``
 
635
 
 
636
 
 
637
  The _prepare_instrumentation alias for
 
638
  prepare_instrumentation has been removed.
 
639
 
 
640
* ``sqlalchemy.orm``
 
641
 
 
642
 
 
643
  Removed the ``EXT_PASS`` alias of ``EXT_CONTINUE``.
 
644
 
 
645
* ``sqlalchemy.engine``
 
646
 
 
647
 
 
648
  The alias from ``DefaultDialect.preexecute_sequences`` to
 
649
  ``.preexecute_pk_sequences`` has been removed.
 
650
 
 
651
  The deprecated engine_descriptors() function has been
 
652
  removed.
 
653
 
 
654
* ``sqlalchemy.ext.activemapper``
 
655
 
 
656
 
 
657
  Module removed.
 
658
 
 
659
* ``sqlalchemy.ext.assignmapper``
 
660
 
 
661
 
 
662
  Module removed.
 
663
 
 
664
* ``sqlalchemy.ext.associationproxy``
 
665
 
 
666
 
 
667
  Pass-through of keyword args on the proxy's
 
668
  ``.append(item, \**kw)`` has been removed and is now
 
669
  simply ``.append(item)``
 
670
 
 
671
* ``sqlalchemy.ext.selectresults``,
 
672
  ``sqlalchemy.mods.selectresults``
 
673
 
 
674
  Modules removed.
 
675
 
 
676
* ``sqlalchemy.ext.declarative``
 
677
 
 
678
 
 
679
  ``declared_synonym()`` removed.
 
680
 
 
681
* ``sqlalchemy.ext.sessioncontext``
 
682
 
 
683
 
 
684
  Module removed.
 
685
 
 
686
* ``sqlalchemy.log``
 
687
 
 
688
 
 
689
  The ``SADeprecationWarning`` alias to
 
690
  ``sqlalchemy.exc.SADeprecationWarning`` has been removed.
 
691
 
 
692
* ``sqlalchemy.exc``
 
693
 
 
694
 
 
695
  ``exc.AssertionError`` has been removed and usage replaced
 
696
  by the Python built-in of the same name.
 
697
 
 
698
* ``sqlalchemy.databases.mysql``
 
699
 
 
700
 
 
701
  The deprecated ``get_version_info`` dialect method has
 
702
  been removed.
 
703
 
 
704
Renamed or Moved
 
705
================
 
706
 
 
707
* ``sqlalchemy.exceptions`` is now ``sqlalchemy.exc``
 
708
 
 
709
 
 
710
  The module may still be imported under the old name until
 
711
  0.6.
 
712
 
 
713
* ``FlushError``, ``ConcurrentModificationError``,
 
714
  ``UnmappedColumnError`` -> sqlalchemy.orm.exc
 
715
 
 
716
  These exceptions moved to the orm package.  Importing
 
717
  'sqlalchemy.orm' will install aliases in sqlalchemy.exc
 
718
  for compatibility until 0.6.
 
719
 
 
720
* ``sqlalchemy.logging`` -> ``sqlalchemy.log``
 
721
 
 
722
 
 
723
  This internal module was renamed.  No longer needs to be
 
724
  special cased when packaging SA with py2app and similar
 
725
  tools that scan imports.
 
726
 
 
727
* ``session.Query().iterate_instances()`` ->
 
728
  ``session.Query().instances()``.
 
729
 
 
730
Deprecated
 
731
==========
 
732
 
 
733
* ``Session.save()``, ``Session.update()``,
 
734
  ``Session.save_or_update()``
 
735
 
 
736
  All three replaced by ``Session.add()``
 
737
 
 
738
* ``sqlalchemy.PassiveDefault``
 
739
 
 
740
 
 
741
  Use ``Column(server_default=...)`` Translates to
 
742
  sqlalchemy.DefaultClause() under the hood.
 
743
 
 
744
* ``session.Query().iterate_instances()``. It has been
 
745
  renamed to ``instances()``.
 
746