1. Mike Bayer
  2. changelog

Source

changelog / CHANGES_08

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
-*- coding: utf-8; fill-column: 68 -*-

=======
CHANGES
=======

0.8.0b1
=======
Changes noted below are specific to version 0.8.
For changes that are in both 0.7 and 0.8, see below
underneath "0.7.xx".

- general
  - SQLAlchemy 0.8 now targets Python 2.5 and
    above.  Python 2.4 is no longer supported.

  - [removed] The "sqlalchemy.exceptions"
    synonym for "sqlalchemy.exc" is removed
    fully.  [ticket:2433]

- orm
  - [removed] The legacy "mutable" system of the
    ORM, including the MutableType class as well
    as the mutable=True flag on PickleType
    and postgresql.ARRAY has been removed.
    In-place mutations are detected by the ORM
    using the sqlalchemy.ext.mutable extension,
    introduced in 0.7.   The removal of MutableType
    and associated constructs removes a great
    deal of complexity from SQLAlchemy's internals.
    The approach performed poorly as it would incur
    a scan of the full contents of the Session
    when in use. [ticket:2442]

  - [moved] The InstrumentationManager interface
    and the entire related system of alternate
    class implementation is now moved out
    to sqlalchemy.ext.instrumentation.   This is
    a seldom used system that adds significant
    complexity and overhead to the mechanics of
    class instrumentation.  The new architecture
    allows it to remain unused until
    InstrumentationManager is actually imported,
    at which point it is bootstrapped into
    the core.

  - [feature] Major rewrite of relationship()
    internals now allow join conditions which
    include columns pointing to themselves
    within composite foreign keys.   A new
    API for very specialized primaryjoin conditions
    is added, allowing conditions based on
    SQL functions, CAST, etc. to be handled
    by placing the annotation functions
    remote() and foreign() inline within the
    expression when necessary.  Previous recipes
    using the semi-private _local_remote_pairs
    approach can be upgraded to this new
    approach. [ticket:1401]

  - [bug] ORM will perform extra effort to determine
    that an FK dependency between two tables is
    not significant during flush if the tables
    are related via joined inheritance and the FK
    dependency is not part of the inherit_condition,
    saves the user a use_alter directive.
    [ticket:2527]

  - [feature] New standalone function with_polymorphic()
    provides the functionality of query.with_polymorphic()
    in a standalone form.   It can be applied to any
    entity within a query, including as the target
    of a join in place of the "of_type()" modifier.
    [ticket:2333]

  - [feature] The of_type() construct on attributes
    now accepts aliased() class constructs as well
    as with_polymorphic constructs, and works with
    query.join(), any(), has(), and also
    eager loaders subqueryload(), joinedload(),
    contains_eager()
    [ticket:2438] [ticket:1106]

  - [feature] Improvements to event listening for
    mapped classes allows that unmapped classes
    can be specified for instance- and mapper-events.
    The established events will be automatically
    set up on subclasses of that class when the
    propagate=True flag is passed, and the
    events will be set up for that class itself
    if and when it is ultimately mapped.
    [ticket:2585]

  - [bug] The instrumentation events class_instrument(),
    class_uninstrument(), and attribute_instrument()
    will now fire off only for descendant classes
    of the class assigned to listen().  Previously,
    an event listener would be assigned to listen
    for all classes in all cases regardless of the
    "target" argument passed.  [ticket:2590]

  - [bug] with_polymorphic() produces JOINs
    in the correct order and with correct inheriting
    tables in the case of sending multi-level
    subclasses in an arbitrary order or with
    intermediary classes missing.  [ticket:1900]

  - [feature] The "deferred declarative
    reflection" system has been moved into the
    declarative extension itself, using the
    new DeferredReflection class.  This
    class is now tested with both single
    and joined table inheritance use cases.
    [ticket:2485]

  - [feature] Added new core function "inspect()",
    which serves as a generic gateway to
    introspection into mappers, objects,
    others.   The Mapper and InstanceState
    objects have been enhanced with a public
    API that allows inspection of mapped
    attributes, including filters for column-bound
    or relationship-bound properties, inspection
    of current object state, history of
    attributes, etc.  [ticket:2208]

  - [feature] Calling rollback() within a
    session.begin_nested() will now only expire
    those objects that had net changes within the
    scope of that transaction, that is objects which
    were dirty or were modified on a flush.  This
    allows the typical use case for begin_nested(),
    that of altering a small subset of objects, to
    leave in place the data from the larger enclosing
    set of objects that weren't modified in
    that sub-transaction.  [ticket:2452]

  - [feature] Added utility feature
    Session.enable_relationship_loading(),
    supersedes relationship.load_on_pending.
    Both features should be avoided, however.
    [ticket:2372]

  - [feature] Added support for .info dictionary argument to
    column_property(), relationship(), composite().
    All MapperProperty classes have an auto-creating .info
    dict available overall.

  - [feature] Adding/removing None from a mapped collection
    now generates attribute events.  Previously, a None
    append would be ignored in some cases.  Related
    to [ticket:2229].

  - [feature] The presence of None in a mapped collection
    now raises an error during flush.   Previously,
    None values in collections would be silently ignored.
    [ticket:2229]

  - [feature] The Query.update() method is now
    more lenient as to the table
    being updated.  Plain Table objects are better
    supported now, and additional a joined-inheritance
    subclass may be used with update(); the subclass
    table will be the target of the update,
    and if the parent table is referenced in the
    WHERE clause, the compiler will call upon
    UPDATE..FROM syntax as allowed by the dialect
    to satisfy the WHERE clause.  MySQL's multi-table
    update feature is also supported if columns
    are specified by object in the "values" dicitionary.
    PG's DELETE..USING is also not available
    in Core yet.

  - [feature] New session events after_transaction_create
    and after_transaction_end
    allows tracking of new SessionTransaction objects.
    If the object is inspected, can be used to determine
    when a session first becomes active and when
    it deactivates.

  - [feature] The Query can now load entity/scalar-mixed
    "tuple" rows that contain
    types which aren't hashable, by setting the flag
    "hashable=False" on the corresponding TypeEngine object
    in use.  Custom types that return unhashable types
    (typically lists) can set this flag to False.
    [ticket:2592]

  - [bug] Improvements to joined/subquery eager
    loading dealing with chains of subclass entities
    sharing a common base, with no specific "join depth"
    provided.  Will chain out to
    each subclass mapper individually before detecting
    a "cycle", rather than considering the base class
    to be the source of the "cycle".  [ticket:2481]

  - [bug] The "passive" flag on Session.is_modified()
    no longer has any effect. is_modified() in
    all cases looks only at local in-memory
    modified flags and will not emit any
    SQL or invoke loader callables/initializers.
    [ticket:2320]

  - [bug] The warning emitted when using
    delete-orphan cascade with one-to-many
    or many-to-many without single-parent=True
    is now an error.  The ORM
    would fail to function subsequent to this
    warning in any case.  [ticket:2405]

  - [bug] Lazy loads emitted within flush events
    such as before_flush(), before_update(),
    etc. will now function as they would
    within non-event code, regarding consideration
    of the PK/FK values used in the lazy-emitted
    query.   Previously,
    special flags would be established that
    would cause lazy loads to load related items
    based on the "previous" value of the
    parent PK/FK values specifically when called
    upon within a flush; the signal to load
    in this way is now localized to where the
    unit of work actually needs to load that
    way.  Note that the UOW does
    sometimes load these collections before
    the before_update() event is called,
    so the usage of "passive_updates" or not
    can affect whether or not a collection will
    represent the "old" or "new" data, when
    accessed within a flush event, based
    on when the lazy load was emitted.
    The change is backwards incompatible in
    the exceedingly small chance that
    user event code depended on the old
    behavior. [ticket:2350]

  - [feature] Query now "auto correlates" by
    default in the same way as select() does.
    Previously, a Query used as a subquery
    in another would require the correlate()
    method be called explicitly in order to
    correlate a table on the inside to the
    outside.  As always, correlate(None)
    disables correlation.  [ticket:2179]

  - [feature] The after_attach event is now
    emitted after the object is established
    in Session.new or Session.identity_map
    upon Session.add(), Session.merge(),
    etc., so that the object is represented
    in these collections when the event
    is called.  Added before_attach
    event to accommodate use cases that
    need autoflush w pre-attached object.
    [ticket:2464]

  - [feature] The Session will produce warnings
    when unsupported methods are used inside the
    "execute" portion of the flush.   These are
    the familiar methods add(), delete(), etc.
    as well as collection and related-object
    manipulations, as called within mapper-level
    flush events
    like after_insert(), after_update(), etc.
    It's been prominently documented for a long
    time that  SQLAlchemy cannot guarantee
    results when the Session is manipulated within
    the execution of the flush plan,
    however users are still doing it, so now
    there's a warning.   Maybe someday the Session
    will be enhanced to support these operations
    inside of the flush, but for now, results
    can't be guaranteed.

  - [bug] Continuing [ticket:2566] regarding extra
    state post-flush due to event listeners;
    any states that are marked as "dirty" from an
    attribute perspective, usually via column-attribute
    set events within after_insert(), after_update(),
    etc., will get the "history" flag reset
    in all cases, instead of only those instances
    that were part of the flush.  This has the effect
    that this "dirty" state doesn't carry over
    after the flush and won't result in UPDATE
    statements.   A warning is emitted to this
    effect; the set_committed_state()
    method can be used to assign attributes on objects
    without producing history events. [ticket:2582]

  - [feature] ORM entities can be passed
    to the core select() construct as well
    as to the select_from(),
    correlate(), and correlate_except()
    methods of select(), where they will be unwrapped
    into selectables. [ticket:2245]

  - [feature] Some support for auto-rendering of a
    relationship join condition based on the mapped
    attribute, with usage of core SQL constructs.
    E.g. select([SomeClass]).where(SomeClass.somerelationship)
    would render SELECT from "someclass" and use the
    primaryjoin of "somerelationship" as the WHERE
    clause.   This changes the previous meaning
    of "SomeClass.somerelationship" when used in a
    core SQL context; previously, it would "resolve"
    to the parent selectable, which wasn't generally
    useful.  Also works with query.filter().
    Related to [ticket:2245].

  - [feature] The registry of classes
    in declarative_base() is now a
    WeakValueDictionary.  So subclasses of
    "Base" that are dereferenced will be
    garbage collected, *if they are not
    referred to by any other mappers/superclass
    mappers*. See the next note for this ticket.
    [ticket:2526]

  - [feature] Conflicts between columns on
    single-inheritance declarative subclasses,
    with or without using a mixin, can be resolved
    using a new @declared_attr usage described
    in the documentation.  [ticket:2472]

  - [feature] declared_attr can now be used
    on non-mixin classes, even though this is generally
    only useful for single-inheritance subclass
    column conflict resolution.  [ticket:2472]

  - [feature] declared_attr can now be used with
    attributes that are not Column or MapperProperty;
    including any user-defined value as well
    as association proxy objects.  [ticket:2517]

  - [bug] Fixed a disconnect that slowly evolved
    between a @declared_attr Column and a
    directly-defined Column on a mixin. In both
    cases, the Column will be applied to the
    declared class' table, but not to that of a
    joined inheritance subclass.   Previously,
    the directly-defined Column would be placed
    on both the base and the sub table, which isn't
    typically what's desired.  [ticket:2565]

  - [feature] *Very limited* support for
    inheriting mappers to be GC'ed when the
    class itself is deferenced.  The mapper
    must not have its own table (i.e.
    single table inh only) without polymorphic
    attributes in place.
    This allows for the use case of
    creating a temporary subclass of a declarative
    mapped class, with no table or mapping
    directives of its own, to be garbage collected
    when dereferenced by a unit test.
    [ticket:2526]

  - [feature] Declarative now maintains a registry
    of classes by string name as well as by full
    module-qualified name.   Multiple classes with the
    same name can now be looked up based on a module-qualified
    string within relationship().   Simple class name
    lookups where more than one class shares the same
    name now raises an informative error message.
    [ticket:2338]

  - [feature] Can now provide class-bound attributes
    that override columns which are of any
    non-ORM type, not just descriptors.
    [ticket:2535]

  - [feature] Added with_labels and
    reduce_columns keyword arguments to
    Query.subquery(), to provide two alternate
    strategies for producing queries with uniquely-
    named columns.  [ticket:1729].

  - [feature] A warning is emitted when a reference
    to an instrumented collection is no longer
    associated with the parent class due to
    expiration/attribute refresh/collection
    replacement, but an append
    or remove operation is received on the
    now-detached collection.  [ticket:2476]

  - [bug] Declarative can now propagate a column
    declared on a single-table inheritance subclass
    up to the parent class' table, when the parent
    class is itself mapped to a join() or select()
    statement, directly or via joined inheritance,
    and not just a Table.   [ticket:2549]

  - [bug] An error is emitted when uselist=False
    is combined with a "dynamic" loader.
    This is a warning in 0.7.9.

  - [removed] Deprecated identifiers removed:

    * allow_null_pks mapper() argument
      (use allow_partial_pks)

    * _get_col_to_prop() mapper method
      (use get_property_by_column())

    * dont_load argument to Session.merge()
      (use load=True)

    * sqlalchemy.orm.shard module
      (use sqlalchemy.ext.horizontal_shard)

- engine
  - [feature] Connection event listeners can
    now be associated with individual
    Connection objects, not just Engine
    objects.  [ticket:2511]

  - [feature] The before_cursor_execute event
    fires off for so-called "_cursor_execute"
    events, which are usually special-case
    executions of primary-key bound sequences
    and default-generation SQL
    phrases that invoke separately when RETURNING
    is not used with INSERT.  [ticket:2459]

  - [feature] The libraries used by the test suite
    have been moved around a bit so that they are
    part of the SQLAlchemy install again.  In addition,
    a new suite of tests is present in the
    new sqlalchemy.testing.suite package.  This is
    an under-development system that hopes to provide
    a universal testing suite for external dialects.
    Dialects which are maintained outside of SQLAlchemy
    can use the new test fixture as the framework
    for their own tests, and will get for free a
    "compliance" suite of dialect-focused tests,
    including an improved "requirements" system
    where specific capabilities and features can
    be enabled or disabled for testing.

  - [bug] The Inspector.get_table_names()
    order_by="foreign_key" feature now sorts
    tables by dependee first, to be consistent
    with util.sort_tables and metadata.sorted_tables.

  - [bug] Fixed bug whereby if a database restart
    affected multiple connections, each
    connection would individually invoke a new
    disposal of the pool, even though only
    one disposal is needed.  [ticket:2522]

  - [feature] Added a new system
    for registration of new dialects in-process
    without using an entrypoint.  See the
    docs for "Registering New Dialects".
    [ticket:2462]

  - [feature] The "required" flag is set to
    True by default, if not passed explicitly,
    on bindparam() if the "value" or "callable"
    parameters are not passed.
    This will cause statement execution to check
    for the parameter being present in the final
    collection of bound parameters, rather than
    implicitly assigning None. [ticket:2556]

  - [feature] Various API tweaks to the "dialect"
    API to better support highly specialized
    systems such as the Akiban database, including
    more hooks to allow an execution context to
    access type processors.

  - [bug] The names of the columns on the
    .c. attribute of a select().apply_labels()
    is now based on <tablename>_<colkey> instead
    of <tablename>_<colname>, for those columns
    that have a distinctly named .key.
    [ticket:2397]

  - [feature] Inspector.get_primary_keys() is
    deprecated; use Inspector.get_pk_constraint().
    Courtesy Diana Clarke.  [ticket:2422]

  - [bug] The autoload_replace flag on Table,
    when False, will cause any reflected foreign key
    constraints which refer to already-declared
    columns to be skipped, assuming that the
    in-Python declared column will take over
    the task of specifying in-Python ForeignKey
    or ForeignKeyConstraint declarations.

  - [bug] The ResultProxy methods inserted_primary_key,
    last_updated_params(), last_inserted_params(),
    postfetch_cols(), prefetch_cols() all
    assert that the given statement is a compiled
    construct, and is an insert() or update()
    statement as is appropriate, else
    raise InvalidRequestError.  [ticket:2498]

  - [feature] New C extension module "utils" has
    been added for additional function speedups
    as we have time to implement.

  - ResultProxy.last_inserted_ids is removed,
    replaced by inserted_primary_key.

- sql
  - [feature] Major rework of operator system
    in Core, to allow redefinition of existing
    operators as well as addition of new operators
    at the type level.  New types can be created
    from existing ones which add or redefine
    operations that are exported out to column
    expressions, in a similar manner to how the
    ORM has allowed comparator_factory.   The new
    architecture moves this capability into the
    Core so that it is consistently usable in
    all cases, propagating cleanly using existing
    type propagation behavior.  [ticket:2547]

  - [feature] To complement [ticket:2547], types
    can now provide "bind expressions" and
    "column expressions" which allow compile-time
    injection of SQL expressions into statements
    on a per-column or per-bind level.   This is
    to suit the use case of a type which needs
    to augment bind- and result- behavior at the
    SQL level, as opposed to in the Python level.
    Allows for schemes like transparent encryption/
    decryption, usage of Postgis functions, etc.
    [ticket:1534]

  - [feature] The Core oeprator system now includes
    the `getitem` operator, i.e. the bracket
    operator in Python.  This is used at first
    to provide index and slice behavior to the
    Postgresql ARRAY type, and also provides a hook
    for end-user definition of custom __getitem__
    schemes which can be applied at the type
    level as well as within ORM-level custom
    operator schemes.   `lshift` (<<)
    and `rshift` (>>) are also supported as
    optional operators.

    Note that this change has the effect that
    descriptor-based __getitem__ schemes used by
    the ORM in conjunction with synonym() or other
    "descriptor-wrapped" schemes will need
    to start using a custom comparator in order
    to maintain this behavior.

  - [feature] Revised the rules used to determine
    the operator precedence for the user-defined
    operator, i.e. that granted using the ``op()``
    method.   Previously, the smallest precedence
    was applied in all cases, now the default
    precedence is zero, lower than all operators
    except "comma" (such as, used in the argument
    list of a ``func`` call) and "AS", and is
    also customizable via the "precedence" argument
    on the ``op()`` method.  [ticket:2537]

  - [feature] Added "collation" parameter to all
    String types.  When present, renders as
    COLLATE <collation>.  This to support the
    COLLATE keyword now supported by several
    databases including MySQL, SQLite, and Postgresql.
    [ticket:2276]

  - [change] The Text() type renders the length
    given to it, if a length was specified.

  - [feature] Custom unary operators can now be
    used by combining operators.custom_op() with
    UnaryExpression().

  - [bug] A tweak to column precedence which moves the
    "concat" and "match" operators to be the same as
    that of "is", "like", and others; this helps with
    parenthesization rendering when used in conjunction
    with "IS". [ticket:2564]

  - [feature] Enhanced GenericFunction and func.*
    to allow for user-defined GenericFunction
    subclasses to be available via the func.*
    namespace automatically by classname,
    optionally using a package name, as well
    as with the ability to have the rendered
    name different from the identified name
    in func.*.

  - [feature] The cast() and extract() constructs
    will now be produced via the func.* accessor
    as well, as users naturally try to access these
    names from func.* they might as well do
    what's expected, even though the returned
    object is not a FunctionElement.
    [ticket:2562]

  - [changed] Most classes in expression.sql
    are no longer preceded with an underscore,
    i.e. Label, SelectBase, Generative, CompareMixin.
    _BindParamClause is also renamed to
    BindParameter.   The old underscore names for
    these classes will remain available as synonyms
    for the foreseeable future.

  - [feature] The Inspector object can now be
    acquired using the new inspect() service,
    part of [ticket:2208]

  - [feature] The column_reflect event now
    accepts the Inspector object as the first
    argument, preceding "table".   Code which
    uses the 0.7 version of this very new
    event will need modification to add the
    "inspector" object as the first argument.
    [ticket:2418]

  - [feature] The behavior of column targeting
    in result sets is now case sensitive by
    default.   SQLAlchemy for many years would
    run a case-insensitive conversion on these values,
    probably to alleviate early case sensitivity
    issues with dialects like Oracle and
    Firebird.   These issues have been more cleanly
    solved in more modern versions so the performance
    hit of calling lower() on identifiers is removed.
    The case insensitive comparisons can be re-enabled
    by setting "case_insensitive=False" on
    create_engine().  [ticket:2423]

  - [bug] Applying a column expression to a select
    statement using a label with or without other
    modifying constructs will no longer "target" that
    expression to the underlying Column; this affects
    ORM operations that rely upon Column targeting
    in order to retrieve results.  That is, a query
    like query(User.id, User.id.label('foo')) will now
    track the value of each "User.id" expression separately
    instead of munging them together.  It is not expected
    that any users will be impacted by this; however,
    a usage that uses select() in conjunction with
    query.from_statement() and attempts to load fully
    composed ORM entities may not function as expected
    if the select() named Column objects with arbitrary
    .label() names, as these will no longer target to
    the Column objects mapped by that entity.
    [ticket:2591]

  - [feature] The "unconsumed column names" warning emitted
    when keys are present in insert.values() or update.values()
    that aren't in the target table is now an exception.
    [ticket:2415]

  - [feature] Added "MATCH" clause to ForeignKey,
    ForeignKeyConstraint, courtesy Ryan Kelly.
    [ticket:2502]

  - [feature] Added support for DELETE and UPDATE from
    an alias of a table, which would assumedly
    be related to itself elsewhere in the query,
    courtesy Ryan Kelly.  [ticket:2507]

  - [feature] select() features a correlate_except()
    method, auto correlates all selectables except those
    passed.

  - [feature] The prefix_with() method is now available
    on each of select(), insert(), update(), delete(),
    all with the same API, accepting multiple
    prefix calls, as well as a "dialect name" so that
    the prefix can be limited to one kind of dialect.
    [ticket:2431]

  - [feature] Added reduce_columns() method
    to select() construct, replaces columns inline
    using the util.reduce_columns utility function
    to remove equivalent columns.  reduce_columns()
    also adds "with_only_synonyms" to limit the
    reduction just to those columns which have the same
    name.  The deprecated fold_equivalents() feature is
    removed [ticket:1729].

  - [feature] Reworked the startswith(), endswith(),
    contains() operators to do a better job with
    negation (NOT LIKE), and also to assemble them
    at compilation time so that their rendered SQL
    can be altered, such as in the case for Firebird
    STARTING WITH [ticket:2470]

  - [feature] Added a hook to the system of rendering
    CREATE TABLE that provides access to the render for each
    Column individually, by constructing a @compiles
    function against the new schema.CreateColumn
    construct.  [ticket:2463]

  - [feature] "scalar" selects now have a WHERE method
    to help with generative building.  Also slight adjustment
    regarding how SS "correlates" columns; the new methodology
    no longer applies meaning to the underlying
    Table column being selected.  This improves
    some fairly esoteric situations, and the logic
    that was there didn't seem to have any purpose.

  - [bug] Fixes to the interpretation of the
    Column "default" parameter as a callable
    to not pass ExecutionContext into a keyword
    argument parameter.  [ticket:2520]

  - [bug] All of UniqueConstraint, ForeignKeyConstraint,
    CheckConstraint, and PrimaryKeyConstraint will
    attach themselves to their parent table automatically
    when they refer to a Table-bound Column object directly
    (i.e. not just string column name), and refer to
    one and only one Table.   Prior to 0.8 this behavior
    occurred for UniqueConstraint and PrimaryKeyConstraint,
    but not ForeignKeyConstraint or CheckConstraint.
    [ticket:2410]

  - [bug] TypeDecorator now includes a generic repr()
    that works in terms of the "impl" type by default.
    This is a behavioral change for those TypeDecorator
    classes that specify a custom __init__ method; those
    types will need to re-define __repr__() if they need
    __repr__() to provide a faithful constructor representation.
    [ticket:2594]

  - [bug] column.label(None) now produces an
    anonymous label, instead of returning the
    column object itself, consistent with the behavior
    of label(column, None).  [ticket:2168]

  - [feature] An explicit error is raised when
    a ForeignKeyConstraint() that was
    constructed to refer to multiple remote tables
    is first used. [ticket:2455]

- access
  - [feature] the MS Access dialect has been
    moved to its own project on Bitbucket,
    taking advantage of the new SQLAlchemy
    dialect compliance suite.   The dialect is
    still in very rough shape and probably not
    ready for general use yet, however
    it does have *extremely* rudimental
    functionality now.
    https://bitbucket.org/zzzeek/sqlalchemy-access

- maxdb
  - [moved] The MaxDB dialect, which hasn't been
    functional for several years, is
    moved out to a pending bitbucket project,
    https://bitbucket.org/zzzeek/sqlalchemy-maxdb.


- sqlite
  - [feature] the SQLite date and time types
    have been overhauled to support a more open
    ended format for input and output, using
    name based format strings and regexps.  A
    new argument "microseconds" also provides
    the option to omit the "microseconds"
    portion of timestamps.  Thanks to
    Nathan Wright for the work and tests on
    this.  [ticket:2363]

- mssql
  - [feature] SQL Server dialect can be given
    database-qualified schema names,
    i.e. "schema='mydatabase.dbo'"; reflection
    operations will detect this, split the schema
    among the "." to get the owner separately,
    and emit a "USE mydatabase" statement before
    reflecting targets within the "dbo" owner;
    the existing database returned from
    DB_NAME() is then restored.

  - [bug] removed legacy behavior whereby
    a column comparison to a scalar SELECT via
    == would coerce to an IN with the SQL server
    dialect.  This is implicit
    behavior which fails in other scenarios
    so is removed.  Code which relies on this
    needs to be modified to use column.in_(select)
    explicitly.  [ticket:2277]

  - [feature] updated support for the mxodbc
    driver; mxodbc 3.2.1 is recommended for full
    compatibility.

- postgresql

  - [feature] postgresql.ARRAY features an optional
    "dimension" argument, will assign a specific
    number of dimensions to the array which will
    render in DDL as ARRAY[][]..., also improves
    performance of bind/result processing.
    [ticket:2441]

  - [feature] postgresql.ARRAY now supports
    indexing and slicing.  The Python [] operator
    is available on all SQL expressions that are
    of type ARRAY; integer or simple slices can be
    passed.  The slices can also be used on the
    assignment side in the SET clause of an UPDATE
    statement by passing them into Update.values();
    see the docs for examples.

  - [feature] Added new "array literal" construct
    postgresql.array().  Basically a "tuple" that
    renders as ARRAY[1,2,3].

  - [feature] Added support for the Postgresql ONLY
    keyword, which can appear corresponding to a
    table in a SELECT, UPDATE, or DELETE statement.
    The phrase is established using with_hint().
    Courtesy Ryan Kelly [ticket:2506]

  - [feature] The "ischema_names" dictionary of the
    Postgresql dialect is "unofficially" customizable.
    Meaning, new types such as PostGIS types can
    be added into this dictionary, and the PG type
    reflection code should be able to handle simple
    types with variable numbers of arguments.
    The functionality here is "unofficial" for
    three reasons:

    1. this is not an "official" API.  Ideally
       an "official" API would allow custom type-handling
       callables at the dialect or global level
       in a generic way.
    2. This is only implemented for the PG dialect,
       in particular because PG has broad support
       for custom types vs. other database backends.
       A real API would be implemented at the
       default dialect level.
    3. The reflection code here is only tested against
       simple types and probably has issues with more
       compositional types.

    patch courtesy Éric Lemoine.

- firebird
  - [feature] The "startswith()" operator renders
    as "STARTING WITH", "~startswith()" renders
    as "NOT STARTING WITH", using FB's more efficient
    operator.  [ticket:2470]

  - [bug] CompileError is raised when VARCHAR with
    no length is attempted to be emitted, same
    way as MySQL. [ticket:2505]

  - [bug] Firebird now uses strict "ansi bind rules"
    so that bound parameters don't render in the
    columns clause of a statement - they render
    literally instead.

  - [bug] Support for passing datetime as date when
    using the DateTime type with Firebird; other
    dialects support this.

  - [feature] An experimental dialect for the fdb
    driver is added, but is untested as I cannot
    get the fdb package to build.  [ticket:2504]

- mysql
  - [bug] Dialect no longer emits expensive server
    collations query, as well as server casing,
    on first connect.  These functions are still
    available as semi-private. [ticket:2404]

  - [feature] Added TIME type to mysql dialect,
    accepts "fst" argument which is the new
    "fractional seconds" specifier for recent
    MySQL versions.  The datatype will interpret
    a microseconds portion received from the driver,
    however note that at this time most/all MySQL
    DBAPIs do not support returning this value.
    [ticket:2534]

- oracle
  - [bug] Quoting information is now passed along
    from a Column with quote=True when generating
    a same-named bound parameter to the bindparam()
    object, as is the case in generated INSERT and UPDATE
    statements, so that unknown reserved names can
    be fully supported.  [ticket:2437]

  - [feature] The types of columns excluded from the
    setinputsizes() set can be customized by sending
    a list of string DBAPI type names to exclude,
    using the exclude_setinputsizes dialect parameter.
    This list was previously fixed.  The list also
    now defaults to STRING, UNICODE, removing
    CLOB, NCLOB from the list.  [ticket:2561]

  - [bug] The CreateIndex construct in Oracle
    will now schema-qualify the name of the index
    to be that of the parent table.  Previously this
    name was omitted which apparently creates the
    index in the default schema, rather than that
    of the table.

- extensions
  - [removed] The SQLSoup extension is removed from
    SQLAlchemy, and is now an external project.
    See http://pypi.python.org/pypi/sqlsoup .
    [ticket:2262]