=======
0.7.10
======
+- changelog
+ - The changelog has been moved to the documentation.
+ This file will be maintained throughout remaining
+ 0.7 maintenance for backwards compabitility, but
+ is removed in 0.8.
+
- orm
- [bug] Fixed Session accounting bug whereby replacing
a deleted object in the identity map with another
--- /dev/null
+import re
+
+def autodoc_skip_member(app, what, name, obj, skip, options):
+ if what == 'class' and skip and \
+ name in ('__init__', '__eq__', '__ne__', '__lt__',
+ '__le__', '__call__') and \
+ obj.__doc__:
+ return False
+ else:
+ return skip
+
+# im sure this is in the app somewhere, but I don't really
+# know where, so we're doing it here.
+_track_autodoced = {}
+def autodoc_process_docstring(app, what, name, obj, options, lines):
+ if what == "class":
+ _track_autodoced[name] = obj
+ elif what in ("attribute", "method") and \
+ options.get("inherited-members"):
+ m = re.match(r'(.*?)\.([\w_]+)$', name)
+ if m:
+ clsname, attrname = m.group(1, 2)
+ if clsname in _track_autodoced:
+ cls = _track_autodoced[clsname]
+ for supercls in cls.__mro__:
+ if attrname in supercls.__dict__:
+ break
+ if supercls is not cls:
+ lines[:0] = [
+ ".. container:: inherited_member",
+ "",
+ " *inherited from the* :%s:`.%s.%s` *%s of* :class:`.%s`" % (
+ "attr" if what == "attribute"
+ else "meth",
+ supercls.__name__,
+ attrname,
+ what,
+ supercls.__name__
+ ),
+ ""
+ ]
+
+
+def setup(app):
+ app.connect('autodoc-skip-member', autodoc_skip_member)
+ app.connect('autodoc-process-docstring', autodoc_process_docstring)
+
+++ /dev/null
-from sphinx.application import TemplateBridge
-from sphinx.builders.html import StandaloneHTMLBuilder
-from sphinx.highlighting import PygmentsBridge
-from sphinx.jinja2glue import BuiltinTemplateLoader
-from pygments import highlight
-from pygments.lexer import RegexLexer, bygroups, using
-from pygments.token import *
-from pygments.filter import Filter, apply_filters
-from pygments.lexers import PythonLexer, PythonConsoleLexer
-from pygments.formatters import HtmlFormatter, LatexFormatter
-import re
-from mako.lookup import TemplateLookup
-from mako.template import Template
-from mako import __version__
-import os
-
-rtd = os.environ.get('READTHEDOCS', None) == 'True'
-
-class MakoBridge(TemplateBridge):
- def init(self, builder, *args, **kw):
- self.jinja2_fallback = BuiltinTemplateLoader()
- self.jinja2_fallback.init(builder, *args, **kw)
-
- builder.config.html_context['release_date'] = builder.config['release_date']
- builder.config.html_context['site_base'] = builder.config['site_base']
-
- self.lookup = TemplateLookup(directories=builder.config.templates_path,
- #format_exceptions=True,
- imports=[
- "from builder import util"
- ]
- )
-
- if rtd:
- import urllib2
- template_url = builder.config['site_base'] + "/docs_base.mako"
- template = urllib2.urlopen(template_url).read()
- self.lookup.put_string("/rtd_base.mako", template)
-
- def render(self, template, context):
- template = template.replace(".html", ".mako")
- context['prevtopic'] = context.pop('prev', None)
- context['nexttopic'] = context.pop('next', None)
- version = context['version']
- pathto = context['pathto']
-
- # RTD layout
- if rtd:
- # add variables if not present, such
- # as if local test of READTHEDOCS variable
- if 'MEDIA_URL' not in context:
- context['MEDIA_URL'] = "http://media.readthedocs.org/"
- if 'slug' not in context:
- context['slug'] = context['project'].lower()
- if 'url' not in context:
- context['url'] = "/some/test/url"
- if 'current_version' not in context:
- context['current_version'] = "latest"
-
- if 'name' not in context:
- context['name'] = context['project'].lower()
-
- context['rtd'] = True
- context['toolbar'] = True
- context['layout'] = "rtd_layout.mako"
- context['base'] = "rtd_base.mako"
- context['pdf_url'] = "%spdf/%s/%s/%s.pdf" % (
- context['MEDIA_URL'],
- context['slug'],
- context['current_version'],
- context['slug']
- )
- # local docs layout
- else:
- context['rtd'] = False
- context['toolbar'] = False
- context['layout'] = "layout.mako"
- context['base'] = "static_base.mako"
-
- context.setdefault('_', lambda x:x)
- return self.lookup.get_template(template).render_unicode(**context)
-
- def render_string(self, template, context):
- # this is used for .js, .css etc. and we don't have
- # local copies of that stuff here so use the jinja render.
- return self.jinja2_fallback.render_string(template, context)
-
-class StripDocTestFilter(Filter):
- def filter(self, lexer, stream):
- for ttype, value in stream:
- if ttype is Token.Comment and re.match(r'#\s*doctest:', value):
- continue
- yield ttype, value
-
-class PyConWithSQLLexer(RegexLexer):
- name = 'PyCon+SQL'
- aliases = ['pycon+sql']
-
- flags = re.IGNORECASE | re.DOTALL
-
- tokens = {
- 'root': [
- (r'{sql}', Token.Sql.Link, 'sqlpopup'),
- (r'{opensql}', Token.Sql.Open, 'opensqlpopup'),
- (r'.*?\n', using(PythonConsoleLexer))
- ],
- 'sqlpopup':[
- (
- r'(.*?\n)((?:PRAGMA|BEGIN|SELECT|INSERT|DELETE|ROLLBACK|COMMIT|ALTER|UPDATE|CREATE|DROP|PRAGMA|DESCRIBE).*?(?:{stop}\n?|$))',
- bygroups(using(PythonConsoleLexer), Token.Sql.Popup),
- "#pop"
- )
- ],
- 'opensqlpopup':[
- (
- r'.*?(?:{stop}\n*|$)',
- Token.Sql,
- "#pop"
- )
- ]
- }
-
-
-class PythonWithSQLLexer(RegexLexer):
- name = 'Python+SQL'
- aliases = ['pycon+sql']
-
- flags = re.IGNORECASE | re.DOTALL
-
- tokens = {
- 'root': [
- (r'{sql}', Token.Sql.Link, 'sqlpopup'),
- (r'{opensql}', Token.Sql.Open, 'opensqlpopup'),
- (r'.*?\n', using(PythonLexer))
- ],
- 'sqlpopup':[
- (
- r'(.*?\n)((?:PRAGMA|BEGIN|SELECT|INSERT|DELETE|ROLLBACK|COMMIT|ALTER|UPDATE|CREATE|DROP|PRAGMA|DESCRIBE).*?(?:{stop}\n?|$))',
- bygroups(using(PythonLexer), Token.Sql.Popup),
- "#pop"
- )
- ],
- 'opensqlpopup':[
- (
- r'.*?(?:{stop}\n*|$)',
- Token.Sql,
- "#pop"
- )
- ]
- }
-
-
-def _strip_trailing_whitespace(iter_):
- buf = list(iter_)
- if buf:
- buf[-1] = (buf[-1][0], buf[-1][1].rstrip())
- for t, v in buf:
- yield t, v
-
-class PopupSQLFormatter(HtmlFormatter):
- def _format_lines(self, tokensource):
- buf = []
- for ttype, value in apply_filters(tokensource, [StripDocTestFilter()]):
- if ttype in Token.Sql:
- for t, v in HtmlFormatter._format_lines(self, iter(buf)):
- yield t, v
- buf = []
-
- if ttype is Token.Sql:
- yield 1, "<div class='show_sql'>%s</div>" % re.sub(r'(?:[{stop}|\n]*)$', '', value)
- elif ttype is Token.Sql.Link:
- yield 1, "<a href='#' class='sql_link'>sql</a>"
- elif ttype is Token.Sql.Popup:
- yield 1, "<div class='popup_sql'>%s</div>" % re.sub(r'(?:[{stop}|\n]*)$', '', value)
- else:
- buf.append((ttype, value))
-
- for t, v in _strip_trailing_whitespace(HtmlFormatter._format_lines(self, iter(buf))):
- yield t, v
-
-class PopupLatexFormatter(LatexFormatter):
- def _filter_tokens(self, tokensource):
- for ttype, value in apply_filters(tokensource, [StripDocTestFilter()]):
- if ttype in Token.Sql:
- if ttype is not Token.Sql.Link and ttype is not Token.Sql.Open:
- yield Token.Literal, re.sub(r'{stop}', '', value)
- else:
- continue
- else:
- yield ttype, value
-
- def format(self, tokensource, outfile):
- LatexFormatter.format(self, self._filter_tokens(tokensource), outfile)
-
-def autodoc_skip_member(app, what, name, obj, skip, options):
- if what == 'class' and skip and \
- name in ('__init__', '__eq__', '__ne__', '__lt__', '__le__', '__call__') and \
- obj.__doc__:
- return False
- else:
- return skip
-
-def setup(app):
- app.add_lexer('pycon+sql', PyConWithSQLLexer())
- app.add_lexer('python+sql', PythonWithSQLLexer())
- app.add_config_value('release_date', "", True)
- app.add_config_value('site_base', "", True)
- app.add_config_value('build_number', "", 1)
- app.connect('autodoc-skip-member', autodoc_skip_member)
- PygmentsBridge.html_formatter = PopupSQLFormatter
- PygmentsBridge.latex_formatter = PopupLatexFormatter
-
--- /dev/null
+import re
+from sphinx.util.compat import Directive
+from docutils.statemachine import StringList
+from docutils import nodes, utils
+import textwrap
+import itertools
+import collections
+import md5
+
+def _comma_list(text):
+ return re.split(r"\s*,\s*", text.strip())
+
+def _parse_content(content):
+ d = {}
+ d['text'] = []
+ idx = 0
+ for line in content:
+ idx += 1
+ m = re.match(r' *\:(.+?)\:(?: +(.+))?', line)
+ if m:
+ attrname, value = m.group(1, 2)
+ d[attrname] = value or ''
+ else:
+ break
+ d["text"] = content[idx:]
+ return d
+
+
+class EnvDirective(object):
+ @property
+ def env(self):
+ return self.state.document.settings.env
+
+class ChangeLogDirective(EnvDirective, Directive):
+ has_content = True
+
+ type_ = "change"
+
+ default_section = 'misc'
+
+ def _organize_by_section(self, changes):
+ compound_sections = [(s, s.split(" ")) for s in
+ self.sections if " " in s]
+
+ bysection = collections.defaultdict(list)
+ all_sections = set()
+ for rec in changes:
+ inner_tag = rec['tags'].intersection(self.inner_tag_sort)
+ if inner_tag:
+ inner_tag = inner_tag.pop()
+ else:
+ inner_tag = ""
+
+ for compound, comp_words in compound_sections:
+ if rec['tags'].issuperset(comp_words):
+ bysection[(compound, inner_tag)].append(rec)
+ all_sections.add(compound)
+ break
+ else:
+ intersect = rec['tags'].intersection(self.sections)
+ if intersect:
+ for sec in rec['sorted_tags']:
+ if sec in intersect:
+ bysection[(sec, inner_tag)].append(rec)
+ all_sections.add(sec)
+ break
+ else:
+ bysection[(self.default_section, inner_tag)].append(rec)
+ return bysection, all_sections
+
+ @classmethod
+ def changes(cls, env):
+ return env.temp_data['ChangeLogDirective_%s_changes' % cls.type_]
+
+ def _setup_run(self):
+ self.sections = self.env.config.changelog_sections
+ self.inner_tag_sort = self.env.config.changelog_inner_tag_sort + [""]
+ self.env.temp_data['ChangeLogDirective_%s_changes' % self.type_] = []
+ self._parsed_content = _parse_content(self.content)
+
+ p = nodes.paragraph('', '',)
+ self.state.nested_parse(self.content[1:], 0, p)
+
+ def run(self):
+ self._setup_run()
+ changes = self.changes(self.env)
+ output = []
+
+ self.version = version = self._parsed_content.get('version', '')
+ id_prefix = "%s-%s" % (self.type_, version)
+ topsection = self._run_top(id_prefix)
+ output.append(topsection)
+
+ bysection, all_sections = self._organize_by_section(changes)
+
+ counter = itertools.count()
+
+ sections_to_render = [s for s in self.sections if s in all_sections]
+ if not sections_to_render:
+ for cat in self.inner_tag_sort:
+ append_sec = self._append_node()
+
+ for rec in bysection[(self.default_section, cat)]:
+ rec["id"] = "%s-%s" % (id_prefix, next(counter))
+
+ self._render_rec(rec, None, cat, append_sec)
+
+ if append_sec.children:
+ topsection.append(append_sec)
+ else:
+ for section in sections_to_render + [self.default_section]:
+ sec = nodes.section('',
+ nodes.title(section, section),
+ ids=["%s-%s" % (id_prefix, section.replace(" ", "-"))]
+ )
+
+ append_sec = self._append_node()
+ sec.append(append_sec)
+
+ for cat in self.inner_tag_sort:
+ for rec in bysection[(section, cat)]:
+ rec["id"] = "%s-%s" % (id_prefix, next(counter))
+ self._render_rec(rec, section, cat, append_sec)
+
+ if append_sec.children:
+ topsection.append(sec)
+
+ return output
+
+ def _append_node(self):
+ return nodes.bullet_list()
+
+ def _run_top(self, id_prefix):
+ version = self._parsed_content.get('version', '')
+ topsection = nodes.section('',
+ nodes.title(version, version),
+ ids=[id_prefix]
+ )
+
+ if self._parsed_content.get("released"):
+ topsection.append(nodes.Text("Released: %s" %
+ self._parsed_content['released']))
+ else:
+ topsection.append(nodes.Text("no release date"))
+ return topsection
+
+
+ def _render_rec(self, rec, section, cat, append_sec):
+ para = rec['node'].deepcopy()
+
+ text = _text_rawsource_from_node(para)
+
+ to_hash = "%s %s" % (self.version, text[0:100])
+ targetid = "%s-%s" % (self.type_,
+ md5.md5(to_hash.encode('ascii', 'ignore')
+ ).hexdigest())
+ targetnode = nodes.target('', '', ids=[targetid])
+ para.insert(0, targetnode)
+ permalink = nodes.reference('', '',
+ nodes.Text("(link)", "(link)"),
+ refid=targetid,
+ classes=['changeset-link']
+ )
+ para.append(permalink)
+
+ insert_ticket = nodes.paragraph('')
+ para.append(insert_ticket)
+
+ i = 0
+ for collection, render, prefix in (
+ (rec['tickets'], self.env.config.changelog_render_ticket, "#%s"),
+ (rec['pullreq'], self.env.config.changelog_render_pullreq,
+ "pull request %s"),
+ (rec['changeset'], self.env.config.changelog_render_changeset, "r%s"),
+ ):
+ for refname in collection:
+ if i > 0:
+ insert_ticket.append(nodes.Text(", ", ", "))
+ else:
+ insert_ticket.append(nodes.Text(" ", " "))
+ i += 1
+ if render is not None:
+ refuri = render % refname
+ node = nodes.reference('', '',
+ nodes.Text(prefix % refname, prefix % refname),
+ refuri=refuri
+ )
+ else:
+ node = nodes.Text(prefix % refname, prefix % refname)
+ insert_ticket.append(node)
+
+ if rec['tags']:
+ tag_node = nodes.strong('',
+ " ".join("[%s]" % t for t
+ in
+ [t1 for t1 in [section, cat]
+ if t1 in rec['tags']] +
+
+ list(rec['tags'].difference([section, cat]))
+ ) + " "
+ )
+ para.children[0].insert(0, tag_node)
+
+ append_sec.append(
+ nodes.list_item('',
+ nodes.target('', '', ids=[rec['id']]),
+ para
+ )
+ )
+
+
+class ChangeDirective(EnvDirective, Directive):
+ has_content = True
+
+ type_ = "change"
+ parent_cls = ChangeLogDirective
+
+ def run(self):
+ content = _parse_content(self.content)
+ p = nodes.paragraph('', '',)
+ sorted_tags = _comma_list(content.get('tags', ''))
+ rec = {
+ 'tags': set(sorted_tags).difference(['']),
+ 'tickets': set(_comma_list(content.get('tickets', ''))).difference(['']),
+ 'pullreq': set(_comma_list(content.get('pullreq', ''))).difference(['']),
+ 'changeset': set(_comma_list(content.get('changeset', ''))).difference(['']),
+ 'node': p,
+ 'type': self.type_,
+ "title": content.get("title", None),
+ 'sorted_tags': sorted_tags
+ }
+
+ if "declarative" in rec['tags']:
+ rec['tags'].add("orm")
+
+ self.state.nested_parse(content['text'], 0, p)
+ self.parent_cls.changes(self.env).append(rec)
+
+ return []
+
+def _text_rawsource_from_node(node):
+ src = []
+ stack = [node]
+ while stack:
+ n = stack.pop(0)
+ if isinstance(n, nodes.Text):
+ src.append(n.rawsource)
+ stack.extend(n.children)
+ return "".join(src)
+
+def _rst2sphinx(text):
+ return StringList(
+ [line.strip() for line in textwrap.dedent(text).split("\n")]
+ )
+
+
+def make_ticket_link(name, rawtext, text, lineno, inliner,
+ options={}, content=[]):
+ env = inliner.document.settings.env
+ render_ticket = env.config.changelog_render_ticket or "%s"
+ prefix = "#%s"
+ if render_ticket:
+ ref = render_ticket % text
+ node = nodes.reference(rawtext, prefix % text, refuri=ref, **options)
+ else:
+ node = nodes.Text(prefix % text, prefix % text)
+ return [node], []
+
+def setup(app):
+ app.add_directive('changelog', ChangeLogDirective)
+ app.add_directive('change', ChangeDirective)
+ app.add_config_value("changelog_sections", [], 'env')
+ app.add_config_value("changelog_inner_tag_sort", [], 'env')
+ app.add_config_value("changelog_render_ticket",
+ None,
+ 'env'
+ )
+ app.add_config_value("changelog_render_pullreq",
+ None,
+ 'env'
+ )
+ app.add_config_value("changelog_render_changeset",
+ None,
+ 'env'
+ )
+ app.add_role('ticket', make_ticket_link)
--- /dev/null
+import re
+from sphinx.util.compat import Directive
+from docutils import nodes
+
+class DialectDirective(Directive):
+ has_content = True
+
+ _dialects = {}
+
+ def _parse_content(self):
+ d = {}
+ d['default'] = self.content[0]
+ d['text'] = []
+ idx = 0
+ for line in self.content[1:]:
+ idx += 1
+ m = re.match(r'\:(.+?)\: +(.+)', line)
+ if m:
+ attrname, value = m.group(1, 2)
+ d[attrname] = value
+ else:
+ break
+ d["text"] = self.content[idx + 1:]
+ return d
+
+ def _dbapi_node(self):
+
+ dialect_name, dbapi_name = self.dialect_name.split("+")
+
+ try:
+ dialect_directive = self._dialects[dialect_name]
+ except KeyError:
+ raise Exception("No .. dialect:: %s directive has been established"
+ % dialect_name)
+
+ output = []
+
+ content = self._parse_content()
+
+ parent_section_ref = self.state.parent.children[0]['ids'][0]
+ self._append_dbapi_bullet(dialect_name, dbapi_name,
+ content['name'], parent_section_ref)
+
+ p = nodes.paragraph('', '',
+ nodes.Text(
+ "Support for the %s database via the %s driver." % (
+ dialect_directive.database_name,
+ content['name']
+ ),
+ "Support for the %s database via the %s driver." % (
+ dialect_directive.database_name,
+ content['name']
+ )
+ ),
+ )
+
+ self.state.nested_parse(content['text'], 0, p)
+ output.append(p)
+
+ if "url" in content or "driverurl" in content:
+ sec = nodes.section(
+ '',
+ nodes.title("DBAPI", "DBAPI"),
+ ids=["dialect-%s-%s-url" % (dialect_name, dbapi_name)]
+ )
+ if "url" in content:
+ text = "Documentation and download information (if applicable) "\
+ "for %s is available at:\n" % content["name"]
+ uri = content['url']
+ sec.append(
+ nodes.paragraph('', '',
+ nodes.Text(text, text),
+ nodes.reference('', '',
+ nodes.Text(uri, uri),
+ refuri=uri,
+ )
+ )
+ )
+ if "driverurl" in content:
+ text = "Drivers for this database are available at:\n"
+ sec.append(
+ nodes.paragraph('', '',
+ nodes.Text(text, text),
+ nodes.reference('', '',
+ nodes.Text(content['driverurl'], content['driverurl']),
+ refuri=content['driverurl']
+ )
+ )
+ )
+ output.append(sec)
+
+
+ if "connectstring" in content:
+ sec = nodes.section(
+ '',
+ nodes.title("Connecting", "Connecting"),
+ nodes.paragraph('', '',
+ nodes.Text("Connect String:", "Connect String:"),
+ nodes.literal_block(content['connectstring'],
+ content['connectstring'])
+ ),
+ ids=["dialect-%s-%s-connect" % (dialect_name, dbapi_name)]
+ )
+ output.append(sec)
+
+ return output
+
+ def _dialect_node(self):
+ self._dialects[self.dialect_name] = self
+
+ content = self._parse_content()
+ self.database_name = content['name']
+
+ self.bullets = nodes.bullet_list()
+ text = "The following dialect/DBAPI options are available. "\
+ "Please refer to individual DBAPI sections for connect information."
+ sec = nodes.section('',
+ nodes.paragraph('', '',
+ nodes.Text(
+ "Support for the %s database." % content['name'],
+ "Support for the %s database." % content['name']
+ ),
+ ),
+ nodes.title("DBAPI Support", "DBAPI Support"),
+ nodes.paragraph('', '',
+ nodes.Text(text, text),
+ self.bullets
+ ),
+ ids=["dialect-%s" % self.dialect_name]
+ )
+
+ return [sec]
+
+ def _append_dbapi_bullet(self, dialect_name, dbapi_name, name, idname):
+ env = self.state.document.settings.env
+ dialect_directive = self._dialects[dialect_name]
+
+ list_node = nodes.list_item('',
+ nodes.paragraph('', '',
+ nodes.reference('', '',
+ nodes.Text(name, name),
+ refdocname=self.docname,
+ refuri=env.app.builder.get_relative_uri(
+ dialect_directive.docname, self.docname) +
+ "#" + idname
+ ),
+ #nodes.Text(" ", " "),
+ #nodes.reference('', '',
+ # nodes.Text("(connectstring)", "(connectstring)"),
+ # refdocname=self.docname,
+ # refuri=env.app.builder.get_relative_uri(
+ # dialect_directive.docname, self.docname) +
+ ## "#" + ("dialect-%s-%s-connect" %
+ # (dialect_name, dbapi_name))
+ # )
+ )
+ )
+ dialect_directive.bullets.append(list_node)
+
+ def run(self):
+ env = self.state.document.settings.env
+ self.docname = env.docname
+
+ self.dialect_name = dialect_name = self.content[0]
+
+ has_dbapi = "+" in dialect_name
+ if has_dbapi:
+ return self._dbapi_node()
+ else:
+ return self._dialect_node()
+
+def setup(app):
+ app.add_directive('dialect', DialectDirective)
+
--- /dev/null
+from __future__ import absolute_import
+
+from sphinx.application import TemplateBridge
+from sphinx.jinja2glue import BuiltinTemplateLoader
+from mako.lookup import TemplateLookup
+import os
+
+rtd = os.environ.get('READTHEDOCS', None) == 'True'
+
+class MakoBridge(TemplateBridge):
+ def init(self, builder, *args, **kw):
+ self.jinja2_fallback = BuiltinTemplateLoader()
+ self.jinja2_fallback.init(builder, *args, **kw)
+
+ builder.config.html_context['release_date'] = builder.config['release_date']
+ builder.config.html_context['site_base'] = builder.config['site_base']
+
+ self.lookup = TemplateLookup(directories=builder.config.templates_path,
+ #format_exceptions=True,
+ imports=[
+ "from builder import util"
+ ]
+ )
+
+ if rtd:
+ import urllib2
+ template_url = builder.config['site_base'] + "/docs_base.mako"
+ template = urllib2.urlopen(template_url).read()
+ self.lookup.put_string("/rtd_base.mako", template)
+
+ def render(self, template, context):
+ template = template.replace(".html", ".mako")
+ context['prevtopic'] = context.pop('prev', None)
+ context['nexttopic'] = context.pop('next', None)
+
+ # RTD layout
+ if rtd:
+ # add variables if not present, such
+ # as if local test of READTHEDOCS variable
+ if 'MEDIA_URL' not in context:
+ context['MEDIA_URL'] = "http://media.readthedocs.org/"
+ if 'slug' not in context:
+ context['slug'] = context['project'].lower()
+ if 'url' not in context:
+ context['url'] = "/some/test/url"
+ if 'current_version' not in context:
+ context['current_version'] = "latest"
+
+ if 'name' not in context:
+ context['name'] = context['project'].lower()
+
+ context['rtd'] = True
+ context['toolbar'] = True
+ context['layout'] = "rtd_layout.mako"
+ context['base'] = "rtd_base.mako"
+ context['pdf_url'] = "%spdf/%s/%s/%s.pdf" % (
+ context['MEDIA_URL'],
+ context['slug'],
+ context['current_version'],
+ context['slug']
+ )
+ # local docs layout
+ else:
+ context['rtd'] = False
+ context['toolbar'] = False
+ context['layout'] = "layout.mako"
+ context['base'] = "static_base.mako"
+
+ context.setdefault('_', lambda x: x)
+ return self.lookup.get_template(template).render_unicode(**context)
+
+ def render_string(self, template, context):
+ # this is used for .js, .css etc. and we don't have
+ # local copies of that stuff here so use the jinja render.
+ return self.jinja2_fallback.render_string(template, context)
+
+def setup(app):
+ app.config['template_bridge'] = "builder.mako.MakoBridge"
+ app.add_config_value('release_date', "", 'env')
+ app.add_config_value('site_base', "", 'env')
+ app.add_config_value('build_number', "", 'env')
+
--- /dev/null
+from pygments.lexer import RegexLexer, bygroups, using
+from pygments.token import Token
+from pygments.filter import Filter
+from pygments.filter import apply_filters
+from pygments.lexers import PythonLexer, PythonConsoleLexer
+from sphinx.highlighting import PygmentsBridge
+from pygments.formatters import HtmlFormatter, LatexFormatter
+
+import re
+
+
+def _strip_trailing_whitespace(iter_):
+ buf = list(iter_)
+ if buf:
+ buf[-1] = (buf[-1][0], buf[-1][1].rstrip())
+ for t, v in buf:
+ yield t, v
+
+
+class StripDocTestFilter(Filter):
+ def filter(self, lexer, stream):
+ for ttype, value in stream:
+ if ttype is Token.Comment and re.match(r'#\s*doctest:', value):
+ continue
+ yield ttype, value
+
+class PyConWithSQLLexer(RegexLexer):
+ name = 'PyCon+SQL'
+ aliases = ['pycon+sql']
+
+ flags = re.IGNORECASE | re.DOTALL
+
+ tokens = {
+ 'root': [
+ (r'{sql}', Token.Sql.Link, 'sqlpopup'),
+ (r'{opensql}', Token.Sql.Open, 'opensqlpopup'),
+ (r'.*?\n', using(PythonConsoleLexer))
+ ],
+ 'sqlpopup': [
+ (
+ r'(.*?\n)((?:PRAGMA|BEGIN|SELECT|INSERT|DELETE|ROLLBACK|'
+ 'COMMIT|ALTER|UPDATE|CREATE|DROP|PRAGMA'
+ '|DESCRIBE).*?(?:{stop}\n?|$))',
+ bygroups(using(PythonConsoleLexer), Token.Sql.Popup),
+ "#pop"
+ )
+ ],
+ 'opensqlpopup': [
+ (
+ r'.*?(?:{stop}\n*|$)',
+ Token.Sql,
+ "#pop"
+ )
+ ]
+ }
+
+
+class PythonWithSQLLexer(RegexLexer):
+ name = 'Python+SQL'
+ aliases = ['pycon+sql']
+
+ flags = re.IGNORECASE | re.DOTALL
+
+ tokens = {
+ 'root': [
+ (r'{sql}', Token.Sql.Link, 'sqlpopup'),
+ (r'{opensql}', Token.Sql.Open, 'opensqlpopup'),
+ (r'.*?\n', using(PythonLexer))
+ ],
+ 'sqlpopup': [
+ (
+ r'(.*?\n)((?:PRAGMA|BEGIN|SELECT|INSERT|DELETE|ROLLBACK'
+ '|COMMIT|ALTER|UPDATE|CREATE|DROP'
+ '|PRAGMA|DESCRIBE).*?(?:{stop}\n?|$))',
+ bygroups(using(PythonLexer), Token.Sql.Popup),
+ "#pop"
+ )
+ ],
+ 'opensqlpopup': [
+ (
+ r'.*?(?:{stop}\n*|$)',
+ Token.Sql,
+ "#pop"
+ )
+ ]
+ }
+
+class PopupSQLFormatter(HtmlFormatter):
+ def _format_lines(self, tokensource):
+ buf = []
+ for ttype, value in apply_filters(tokensource, [StripDocTestFilter()]):
+ if ttype in Token.Sql:
+ for t, v in HtmlFormatter._format_lines(self, iter(buf)):
+ yield t, v
+ buf = []
+
+ if ttype is Token.Sql:
+ yield 1, "<div class='show_sql'>%s</div>" % \
+ re.sub(r'(?:[{stop}|\n]*)$', '', value)
+ elif ttype is Token.Sql.Link:
+ yield 1, "<a href='#' class='sql_link'>sql</a>"
+ elif ttype is Token.Sql.Popup:
+ yield 1, "<div class='popup_sql'>%s</div>" % \
+ re.sub(r'(?:[{stop}|\n]*)$', '', value)
+ else:
+ buf.append((ttype, value))
+
+ for t, v in _strip_trailing_whitespace(
+ HtmlFormatter._format_lines(self, iter(buf))):
+ yield t, v
+
+class PopupLatexFormatter(LatexFormatter):
+ def _filter_tokens(self, tokensource):
+ for ttype, value in apply_filters(tokensource, [StripDocTestFilter()]):
+ if ttype in Token.Sql:
+ if ttype is not Token.Sql.Link and ttype is not Token.Sql.Open:
+ yield Token.Literal, re.sub(r'{stop}', '', value)
+ else:
+ continue
+ else:
+ yield ttype, value
+
+ def format(self, tokensource, outfile):
+ LatexFormatter.format(self, self._filter_tokens(tokensource), outfile)
+
+def setup(app):
+ app.add_lexer('pycon+sql', PyConWithSQLLexer())
+ app.add_lexer('python+sql', PythonWithSQLLexer())
+
+ PygmentsBridge.html_formatter = PopupSQLFormatter
+ PygmentsBridge.latex_formatter = PopupLatexFormatter
+
--- /dev/null
+
+==============
+0.1 Changelog
+==============
+
+
+.. changelog::
+ :version: 0.1.7
+ :released: Fri May 05 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ some fixes to topological sort algorithm
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added DISTINCT ON support to Postgres (just supply distinct=[col1,col2..])
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added __mod__ (% operator) to sql expressions
+
+ .. change::
+ :tags:
+ :tickets:
+
+ "order_by" mapper property inherited from inheriting mapper
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to column type used when mapper UPDATES/DELETEs
+
+ .. change::
+ :tags:
+ :tickets:
+
+ with convert_unicode=True, reflection was failing, has been fixed
+
+ .. change::
+ :tags:
+ :tickets:
+
+ types types types! still werent working....have to use TypeDecorator again :(
+
+ .. change::
+ :tags:
+ :tickets:
+
+ mysql binary type converts array output to buffer, fixes PickleType
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed the attributes.py memory leak once and for all
+
+ .. change::
+ :tags:
+ :tickets:
+
+ unittests are qualified based on the databases that support each one
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed bug where column defaults would clobber VALUES clause of insert objects
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed bug where table def w/ schema name would force engine connection
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix for parenthesis to work correctly with subqueries in INSERT/UPDATE
+
+ .. change::
+ :tags:
+ :tickets:
+
+ HistoryArraySet gets extend() method
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed lazyload support for other comparison operators besides =
+
+ .. change::
+ :tags:
+ :tickets:
+
+ lazyload fix where two comparisons in the join condition point to the
+ samem column
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "construct_new" flag to mapper, will use __new__ to create instances
+ instead of __init__ (standard in 0.2)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added selectresults.py to SVN, missed it last time
+
+ .. change::
+ :tags:
+ :tickets:
+
+ tweak to allow a many-to-many relationship from a table to itself via
+ an association table
+
+ .. change::
+ :tags:
+ :tickets:
+
+ small fix to "translate_row" function used by polymorphic example
+
+ .. change::
+ :tags:
+ :tickets:
+
+ create_engine uses cgi.parse_qsl to read query string (out the window in 0.2)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ tweaks to CAST operator
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed function names LOCAL_TIME/LOCAL_TIMESTAMP -> LOCALTIME/LOCALTIMESTAMP
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed order of ORDER BY/HAVING in compile
+
+.. changelog::
+ :version: 0.1.6
+ :released: Wed Apr 12 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ support for MS-SQL added courtesy Rick Morrison, Runar Petursson
+
+ .. change::
+ :tags:
+ :tickets:
+
+ the latest SQLSoup from J. Ellis
+
+ .. change::
+ :tags:
+ :tickets:
+
+ ActiveMapper has preliminary support for inheritance (Jeff Watkins)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added a "mods" system which allows pluggable modules that modify/augment
+ core functionality, using the function "install_mods(*modnames)".
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added the first "mod", SelectResults, which modifies mapper selects to
+ return generators that turn ranges into LIMIT/OFFSET queries
+ (Jonas Borgstr?
+
+ .. change::
+ :tags:
+ :tickets:
+
+ factored out querying capabilities of Mapper into a separate Query object
+ which is Session-centric. this improves the performance of mapper.using(session)
+ and makes other things possible.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ objectstore/Session refactored, the official way to save objects is now
+ via the flush() method. The begin/commit functionality of Session is factored
+ into LegacySession which is still established as the default behavior, until
+ the 0.2 series.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ types system is bound to an engine at query compile time, not schema
+ construction time. this simplifies the types system as well as the ProxyEngine.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added 'version_id' keyword argument to mapper. this keyword should reference a
+ Column object with type Integer, preferably non-nullable, which will be used on
+ the mapped table to track version numbers. this number is incremented on each
+ save operation and is specifed in the UPDATE/DELETE conditions so that it
+ factors into the returned row count, which results in a ConcurrencyError if the
+ value received is not the expected count.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added 'entity_name' keyword argument to mapper. a mapper is now associated
+ with a class via the class object as well as an optional entity_name parameter,
+ which is a string defaulting to None. any number of primary mappers can be
+ created for a class, qualified by the entity name. instances of those classes
+ will issue all of their load and save operations through their
+ entity_name-qualified mapper, and maintain separate a identity in the identity
+ map for an otherwise equilvalent object.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to the attributes system. code has been clarified, and also fixed to
+ support proper polymorphic behavior on object attributes.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "for_update" flag to Select objects
+
+ .. change::
+ :tags:
+ :tickets:
+
+ some fixes for backrefs
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix for postgres1 DateTime type
+
+ .. change::
+ :tags:
+ :tickets:
+
+ documentation pages mostly switched over to Markdown syntax
+
+.. changelog::
+ :version: 0.1.5
+ :released: Mon Mar 27 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added SQLSession concept to SQLEngine. this object keeps track of retrieving a
+ connection from the connection pool as well as an in-progress transaction.
+ methods push_session() and pop_session() added to SQLEngine which push/pop a new
+ SQLSession onto the engine, allowing operation upon a second connection "nested"
+ within the previous one, allowing nested transactions. Other tricks are sure to
+ come later regarding SQLSession.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added nest_on argument to objectstore.Session. This is a single SQLEngine or
+ list of engines for which push_session()/pop_session() will be called each time
+ this Session becomes the active session (via objectstore.push_session() or
+ equivalent). This allows a unit of work Session to take advantage of the nested
+ transaction feature without explicitly calling push_session/pop_session on the
+ engine.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ factored apart objectstore/unitofwork to separate "Session scoping" from
+ "uow commit heavy lifting"
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added populate_instance() method to MapperExtension. allows an extension to
+ modify the population of object attributes. this method can call the
+ populate_instance() method on another mapper to proxy the attribute population
+ from one mapper to another; some row translation logic is also built in to help
+ with this.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed Oracle8-compatibility "use_ansi" flag which converts JOINs to
+ comparisons with the = and (+) operators, passes basic unittests
+
+ .. change::
+ :tags:
+ :tickets:
+
+ tweaks to Oracle LIMIT/OFFSET support
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Oracle reflection uses ALL_** views instead of USER_** to get larger
+ list of stuff to reflect from
+
+ .. change::
+ :tags:
+ :tickets: 105
+
+ fixes to Oracle foreign key reflection
+
+ .. change::
+ :tags:
+ :tickets:
+
+ objectstore.commit(obj1, obj2,...) adds an extra step to seek out private
+ relations on properties and delete child objects, even though its not a global
+ commit
+
+ .. change::
+ :tags:
+ :tickets:
+
+ lots and lots of fixes to mappers which use inheritance, strengthened the
+ concept of relations on a mapper being made towards the "local" table for that
+ mapper, not the tables it inherits. allows more complex compositional patterns
+ to work with lazy/eager loading.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added support for mappers to inherit from others based on the same table,
+ just specify the same table as that of both parent/child mapper.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ some minor speed improvements to the attributes system with regards to
+ instantiating and populating new objects.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed MySQL binary unit test
+
+ .. change::
+ :tags:
+ :tickets:
+
+ INSERTs can receive clause elements as VALUES arguments, not just literal
+ values
+
+ .. change::
+ :tags:
+ :tickets:
+
+ support for calling multi-tokened functions, i.e. schema.mypkg.func()
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added J. Ellis' SQLSoup module to extensions package
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "polymorphic" examples illustrating methods to load multiple object types
+ from one mapper, the second of which uses the new populate_instance() method.
+ small improvements to mapper, UNION construct to help the examples along
+
+ .. change::
+ :tags:
+ :tickets:
+
+ improvements/fixes to session.refresh()/session.expire() (which may have
+ been called "invalidate" earlier..)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added session.expunge() which totally removes an object from the current
+ session
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added *args, **kwargs pass-thru to engine.transaction(func) allowing easier
+ creation of transactionalizing decorator functions
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added iterator interface to ResultProxy: "for row in result:..."
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added assertion to tx = session.begin(); tx.rollback(); tx.begin(), i.e. cant
+ use it after a rollback()
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added date conversion on bind parameter fix to SQLite enabling dates to
+ work with pysqlite1
+
+ .. change::
+ :tags:
+ :tickets: 116
+
+ improvements to subqueries to more intelligently construct their FROM
+ clauses
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added PickleType to types.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed two bugs with column labels with regards to bind parameters: bind param
+ keynames they are now generated from a column "label" in all relevant cases to
+ take advantage of excess-name-length rules, and checks for a peculiar collision
+ against a column named the same as "tablename_colname" added
+
+ .. change::
+ :tags:
+ :tickets:
+
+ major overhaul to unit of work documentation, other documentation sections.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed attributes bug where if an object is committed, its lazy-loaded list got
+ blown away if it hadnt been loaded
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added unique_connection() method to engine, connection pool to return a
+ connection that is not part of the thread-local context or any current
+ transaction
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added invalidate() function to pooled connection. will remove the connection
+ from the pool. still need work for engines to auto-reconnect to a stale DB
+ though.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added distinct() function to column elements so you can do
+ func.count(mycol.distinct())
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "always_refresh" flag to Mapper, creates a mapper that will always
+ refresh the attributes of objects it gets/selects from the DB, overwriting any
+ changes made.
+
+.. changelog::
+ :version: 0.1.4
+ :released: Mon Mar 13 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ create_engine() now uses genericized parameters; host/hostname,
+ db/dbname/database, password/passwd, etc. for all engine connections. makes
+ engine URIs much more "universal"
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added support for SELECT statements embedded into a column clause, using the
+ flag "scalar=True"
+
+ .. change::
+ :tags:
+ :tickets:
+
+ another overhaul to EagerLoading when used in conjunction with mappers that
+ inherit; improvements to eager loads figuring out their aliased queries
+ correctly, also relations set up against a mapper with inherited mappers will
+ create joins against the table that is specific to the mapper itself (i.e. and
+ not any tables that are inherited/are further down the inheritance chain),
+ this can be overridden by using custom primary/secondary joins.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added J.Ellis patch to mapper.py so that selectone() throws an exception
+ if query returns more than one object row, selectfirst() to not throw the
+ exception. also adds selectfirst_by (synonymous with get_by) and selectone_by
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added onupdate parameter to Column, will exec SQL/python upon an update
+ statement.Also adds "for_update=True" to all DefaultGenerator subclasses
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added support for Oracle table reflection contributed by Andrija Zaric;
+ still some bugs to work out regarding composite primary keys/dictionary selection
+
+ .. change::
+ :tags:
+ :tickets:
+
+ checked in an initial Firebird module, awaiting testing.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added sql.ClauseParameters dictionary object as the result for
+ compiled.get_params(), does late-typeprocessing of bind parameters so
+ that the original values are easier to access
+
+ .. change::
+ :tags:
+ :tickets:
+
+ more docs for indexes, column defaults, connection pooling, engine construction
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to the construction of the types system. uses a simpler inheritance
+ pattern so that any of the generic types can be easily subclassed, with no need
+ for TypeDecorator.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "convert_unicode=False" parameter to SQLEngine, will cause all String
+ types to perform unicode encoding/decoding (makes Strings act like Unicodes)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added 'encoding="utf8"' parameter to engine. the given encoding will be
+ used for all encode/decode calls within Unicode types as well as Strings
+ when convert_unicode=True.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ improved support for mapping against UNIONs, added polymorph.py example
+ to illustrate multi-class mapping against a UNION
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to SQLite LIMIT/OFFSET syntax
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to Oracle LIMIT syntax
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added backref() function, allows backreferences to have keyword arguments
+ that will be passed to the backref.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Sequences and ColumnDefault objects can do execute()/scalar() standalone
+
+ .. change::
+ :tags:
+ :tickets:
+
+ SQL functions (i.e. func.foo()) can do execute()/scalar() standalone
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to SQL functions so that the ANSI-standard functions, i.e. current_timestamp
+ etc., do not specify parenthesis. all other functions do.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added settattr_clean and append_clean to SmartProperty, which set
+ attributes without triggering a "dirty" event or any history. used as:
+ myclass.prop1.setattr_clean(myobject, 'hi')
+
+ .. change::
+ :tags:
+ :tickets:
+
+ improved support to column defaults when used by mappers; mappers will pull
+ pre-executed defaults from statement's executed bind parameters
+ (pre-conversion) to populate them into a saved object's attributes; if any
+ PassiveDefaults have fired off, will instead post-fetch the row from the DB to
+ populate the object.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added 'get_session().invalidate(*obj)' method to objectstore, instances will
+ refresh() themselves upon the next attribute access.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ improvements to SQL func calls including an "engine" keyword argument so
+ they can be execute()d or scalar()ed standalone, also added func accessor to
+ SQLEngine
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to MySQL4 custom table engines, i.e. TYPE instead of ENGINE
+
+ .. change::
+ :tags:
+ :tickets:
+
+ slightly enhanced logging, includes timestamps and a somewhat configurable
+ formatting system, in lieu of a full-blown logging system
+
+ .. change::
+ :tags:
+ :tickets:
+
+ improvements to the ActiveMapper class from the TG gang, including
+ many-to-many relationships
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added Double and TinyInt support to mysql
+
+.. changelog::
+ :version: 0.1.3
+ :released: Thu Mar 02 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ completed "post_update" feature, will add a second update statement before
+ inserts and after deletes in order to reconcile a relationship without any
+ dependencies being created; used when persisting two rows that are dependent
+ on each other
+
+ .. change::
+ :tags:
+ :tickets:
+
+ completed mapper.using(session) function, localized per-object Session
+ functionality; objects can be declared and manipulated as local to any
+ user-defined Session
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to Oracle "row_number over" clause with multiple tables
+
+ .. change::
+ :tags:
+ :tickets:
+
+ mapper.get() was not selecting multiple-keyed objects if the mapper's table was a join,
+ such as in an inheritance relationship, this is fixed.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to sql/schema packages so that the sql package can run all on its own,
+ producing selects, inserts, etc. without any engine dependencies. builds upon
+ new TableClause/ColumnClause lexical objects. Schema's Table/Column objects
+ are the "physical" subclasses of them. simplifies schema/sql relationship,
+ extensions (like proxyengine), and speeds overall performance by a large margin.
+ removes the entire getattr() behavior that plagued 0.1.1.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ refactoring of how the mapper "synchronizes" data between two objects into a
+ separate module, works better with properties attached to a mapper that has an
+ additional inheritance relationship to one of the related tables, also the same
+ methodology used to synchronize parent/child objects now used by mapper to
+ synchronize between inherited and inheriting mappers.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ made objectstore "check for out-of-identitymap" more aggressive, will perform the
+ check when object attributes are modified or the object is deleted
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Index object fully implemented, can be constructed standalone, or via
+ "index" and "unique" arguments on Columns.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "convert_unicode" flag to SQLEngine, will treat all String/CHAR types
+ as Unicode types, with raw-byte/utf-8 translation on the bind parameter and
+ result set side.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ postgres maintains a list of ANSI functions that must have no parenthesis so
+ function calls with no arguments work consistently
+
+ .. change::
+ :tags:
+ :tickets:
+
+ tables can be created with no engine specified. this will default their engine
+ to a module-scoped "default engine" which is a ProxyEngine. this engine can
+ be connected via the function "global_connect".
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "refresh(*obj)" method to objectstore / Session to reload the attributes of
+ any set of objects from the database unconditionally
+
+.. changelog::
+ :version: 0.1.2
+ :released: Fri Feb 24 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed a recursive call in schema that was somehow running 994 times then returning
+ normally. broke nothing, slowed down everything. thanks to jpellerin for finding this.
+
+.. changelog::
+ :version: 0.1.1
+ :released: Thu Feb 23 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ small fix to Function class so that expressions with a func.foo() use the type of the
+ Function object (i.e. the left side) as the type of the boolean expression, not the
+ other side which is more of a moving target (changeset 1020).
+
+ .. change::
+ :tags:
+ :tickets:
+
+ creating self-referring mappers with backrefs slightly easier (but still not that easy -
+ changeset 1019)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixes to one-to-one mappings (changeset 1015)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ psycopg1 date/time issue with None fixed (changeset 1005)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ two issues related to postgres, which doesnt want to give you the "lastrowid"
+ since oids are deprecated:
+ * postgres database-side defaults that are on primary key cols *do* execute
+ explicitly beforehand, even though thats not the idea of a PassiveDefault. this is
+ because sequences on columns get reflected as PassiveDefaults, but need to be explicitly
+ executed on a primary key col so we know what we just inserted.
+ * if you did add a row that has a bunch of database-side defaults on it,
+ and the PassiveDefault thing was working the old way, i.e. they just execute on
+ the DB side, the "cant get the row back without an OID" exception that occurred
+ also will not happen unless someone (usually the ORM) explicitly asks for it.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed a glitch with engine.execute_compiled where it was making a second
+ ResultProxy that just got thrown away.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ began to implement newer logic in object properities. you can now say
+ myclass.attr.property, which will give you the PropertyLoader corresponding to that
+ attribute, i.e. myclass.mapper.props['attr']
+
+ .. change::
+ :tags:
+ :tickets:
+
+ eager loading has been internally overhauled to use aliases at all times. more
+ complicated chains of eager loads can now be created without any need for explicit
+ "use aliases"-type instructions. EagerLoader code is also much simpler now.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ a new somewhat experimental flag "use_update" added to relations, indicates that
+ this relationship should be handled by a second UPDATE statement, either after a
+ primary INSERT or before a primary DELETE. handles circular row dependencies.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added exceptions module, all raised exceptions (except for some
+ KeyError/AttributeError exceptions) descend from these classes.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to date types with MySQL, returned timedelta converted to datetime.time
+
+ .. change::
+ :tags:
+ :tickets:
+
+ two-phase objectstore.commit operations (i.e. begin/commit) now return a
+ transactional object (SessionTrans), to more clearly indicate transaction boundaries.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Index object with create/drop support added to schema
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to postgres, where it will explicitly pre-execute a PassiveDefault on a table
+ if it is a primary key column, pursuant to the ongoing "we cant get inserted rows
+ back from postgres" issue
+
+ .. change::
+ :tags:
+ :tickets:
+
+ change to information_schema query that gets back postgres table defs, now
+ uses explicit JOIN keyword, since one user had faster performance with 8.1
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to engine.process_defaults so it works correctly with a table that has
+ different column name/column keys (changset 982)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ a column can only be attached to one table - this is now asserted
+
+ .. change::
+ :tags:
+ :tickets:
+
+ postgres time types descend from Time type
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to alltests so that it runs types test (now named testtypes)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to Join object so that it correctly exports its foreign keys (cs 973)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ creating relationships against mappers that use inheritance fixed (cs 973)
--- /dev/null
+
+==============
+0.2 Changelog
+==============
+
+
+.. changelog::
+ :version: 0.2.8
+ :released: Tue Sep 05 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ cleanup on connection methods + documentation. custom DBAPI
+ arguments specified in query string, 'connect_args' argument
+ to 'create_engine', or custom creation function via 'creator'
+ function to 'create_engine'.
+
+ .. change::
+ :tags:
+ :tickets: 274
+
+ added "recycle" argument to Pool, is "pool_recycle" on create_engine,
+ defaults to 3600 seconds; connections after this age will be closed and
+ replaced with a new one, to handle db's that automatically close
+ stale connections
+
+ .. change::
+ :tags:
+ :tickets: 121
+
+ changed "invalidate" semantics with pooled connection; will
+ instruct the underlying connection record to reconnect the next
+ time its called. "invalidate" will also automatically be called
+ if any error is thrown in the underlying call to connection.cursor().
+ this will hopefully allow the connection pool to reconnect to a
+ database that had been stopped and started without restarting
+ the connecting application
+
+ .. change::
+ :tags:
+ :tickets:
+
+ eesh ! the tutorial doctest was broken for quite some time.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ add_property() method on mapper does a "compile all mappers"
+ step in case the given property references a non-compiled mapper
+ (as it did in the case of the tutorial !)
+
+ .. change::
+ :tags:
+ :tickets: 277
+
+ check for pg sequence already existing before create
+
+ .. change::
+ :tags:
+ :tickets:
+
+ if a contextual session is established via MapperExtension.get_session
+ (as it is using the sessioncontext plugin, etc), a lazy load operation
+ will use that session by default if the parent object is not
+ persistent with a session already.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ lazy loads will not fire off for an object that does not have a
+ database identity (why?
+ see http://www.sqlalchemy.org/trac/wiki/WhyDontForeignKeysLoadData)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ unit-of-work does a better check for "orphaned" objects that are
+ part of a "delete-orphan" cascade, for certain conditions where the
+ parent isnt available to cascade from.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ mappers can tell if one of their objects is an "orphan" based
+ on interactions with the attribute package. this check is based
+ on a status flag maintained for each relationship
+ when objects are attached and detached from each other.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ it is now invalid to declare a self-referential relationship with
+ "delete-orphan" (as the abovementioned check would make them impossible
+ to save)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ improved the check for objects being part of a session when the
+ unit of work seeks to flush() them as part of a relationship..
+
+ .. change::
+ :tags:
+ :tickets: 280
+
+ statement execution supports using the same BindParam
+ object more than once in an expression; simplified handling of positional
+ parameters. nice job by Bill Noon figuring out the basic idea.
+
+ .. change::
+ :tags:
+ :tickets: 60, 71
+
+ postgres reflection moved to use pg_schema tables, can be overridden
+ with use_information_schema=True argument to create_engine.
+
+ .. change::
+ :tags:
+ :tickets: 155
+
+ added case_sensitive argument to MetaData, Table, Column, determines
+ itself automatically based on if a parent schemaitem has a non-None
+ setting for the flag, or if not, then whether the identifier name is all lower
+ case or not. when set to True, quoting is applied to identifiers with mixed or
+ uppercase identifiers. quoting is also applied automatically in all cases to
+ identifiers that are known to be reserved words or contain other non-standard
+ characters. various database dialects can override all of this behavior, but
+ currently they are all using the default behavior. tested with postgres, mysql,
+ sqlite, oracle. needs more testing with firebird, ms-sql. part of the ongoing
+ work with
+
+ .. change::
+ :tags:
+ :tickets:
+
+ unit tests updated to run without any pysqlite installed; pool
+ test uses a mock DBAPI
+
+ .. change::
+ :tags:
+ :tickets: 281
+
+ urls support escaped characters in passwords
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added limit/offset to UNION queries (though not yet in oracle)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "timezone=True" flag to DateTime and Time types. postgres
+ so far will convert this to "TIME[STAMP] (WITH|WITHOUT) TIME ZONE",
+ so that control over timezone presence is more controllable (psycopg2
+ returns datetimes with tzinfo's if available, which can create confusion
+ against datetimes that dont).
+
+ .. change::
+ :tags:
+ :tickets: 287
+
+ fix to using query.count() with distinct, **kwargs with SelectResults
+ count()
+
+ .. change::
+ :tags:
+ :tickets: 289
+
+ deregister Table from MetaData when autoload fails;
+
+ .. change::
+ :tags:
+ :tickets: 293
+
+ import of py2.5s sqlite3
+
+ .. change::
+ :tags:
+ :tickets: 296
+
+ unicode fix for startswith()/endswith()
+
+.. changelog::
+ :version: 0.2.7
+ :released: Sat Aug 12 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ quoting facilities set up so that database-specific quoting can be
+ turned on for individual table, schema, and column identifiers when
+ used in all queries/creates/drops. Enabled via "quote=True" in
+ Table or Column, as well as "quote_schema=True" in Table. Thanks to
+ Aaron Spike for his excellent efforts.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ assignmapper was setting is_primary=True, causing all sorts of mayhem
+ by not raising an error when redundant mappers were set up, fixed
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added allow_null_pks option to Mapper, allows rows where some
+ primary key columns are null (i.e. when mapping to outer joins etc)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ modifcation to unitofwork to not maintain ordering within the
+ "new" list or within the UOWTask "objects" list; instead, new objects
+ are tagged with an ordering identifier as they are registered as new
+ with the session, and the INSERT statements are then sorted within the
+ mapper save_obj. the INSERT ordering has basically been pushed all
+ the way to the end of the flush cycle. that way the various sorts and
+ organizations occuring within UOWTask (particularly the circular task
+ sort) dont have to worry about maintaining order (which they werent anyway)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed reflection of foreign keys to autoload the referenced table
+ if it was not loaded already
+
+ .. change::
+ :tags:
+ :tickets: 256
+
+ - pass URL query string arguments to connect() function
+
+ .. change::
+ :tags:
+ :tickets: 257
+
+ - oracle boolean type
+
+ .. change::
+ :tags:
+ :tickets:
+
+ custom primary/secondary join conditions in a relation *will* be propagated
+ to backrefs by default. specifying a backref() will override this behavior.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ better check for ambiguous join conditions in sql.Join; propagates to a
+ better error message in PropertyLoader (i.e. relation()/backref()) for when
+ the join condition can't be reasonably determined.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ sqlite creates ForeignKeyConstraint objects properly upon table
+ reflection.
+
+ .. change::
+ :tags:
+ :tickets: 224
+
+ adjustments to pool stemming from changes made for.
+ overflow counter should only be decremented if the connection actually
+ succeeded. added a test script to attempt testing this.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed mysql reflection of default values to be PassiveDefault
+
+ .. change::
+ :tags:
+ :tickets: 263, 264
+
+ added reflected 'tinyint', 'mediumint' type to MS-SQL.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ SingletonThreadPool has a size and does a cleanup pass, so that
+ only a given number of thread-local connections stay around (needed
+ for sqlite applications that dispose of threads en masse)
+
+ .. change::
+ :tags:
+ :tickets: 267, 265
+
+ fixed small pickle bug(s) with lazy loaders
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed possible error in mysql reflection where certain versions
+ return an array instead of string for SHOW CREATE TABLE call
+
+ .. change::
+ :tags:
+ :tickets: 1770
+
+ fix to lazy loads when mapping to joins
+
+ .. change::
+ :tags:
+ :tickets:
+
+ all create()/drop() calls have a keyword argument of "connectable".
+ "engine" is deprecated.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed ms-sql connect() to work with adodbapi
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "nowait" flag to Select()
+
+ .. change::
+ :tags:
+ :tickets: 271
+
+ inheritance check uses issubclass() instead of direct __mro__ check
+ to make sure class A inherits from B, allowing mapper inheritance to more
+ flexibly correspond to class inheritance
+
+ .. change::
+ :tags:
+ :tickets: 252
+
+ SelectResults will use a subselect, when calling an aggregate (i.e.
+ max, min, etc.) on a SelectResults that has an ORDER BY clause
+
+ .. change::
+ :tags:
+ :tickets: 269
+
+ fixes to types so that database-specific types more easily used;
+ fixes to mysql text types to work with this methodology
+
+ .. change::
+ :tags:
+ :tickets:
+
+ some fixes to sqlite date type organization
+
+ .. change::
+ :tags:
+ :tickets: 263
+
+ added MSTinyInteger to MS-SQL
+
+.. changelog::
+ :version: 0.2.6
+ :released: Thu Jul 20 2006
+
+ .. change::
+ :tags:
+ :tickets: 76
+
+ big overhaul to schema to allow truly composite primary and foreign
+ key constraints, via new ForeignKeyConstraint and PrimaryKeyConstraint
+ objects.
+ Existing methods of primary/foreign key creation have not been changed
+ but use these new objects behind the scenes. table creation
+ and reflection is now more table oriented rather than column oriented.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to MapperExtension calling scheme, wasnt working very well
+ previously
+
+ .. change::
+ :tags:
+ :tickets:
+
+ tweaks to ActiveMapper, supports self-referential relationships
+
+ .. change::
+ :tags:
+ :tickets:
+
+ slight rearrangement to objectstore (in activemapper/threadlocal)
+ so that the SessionContext is referenced by '.context' instead
+ of subclassed directly.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ activemapper will use threadlocal's objectstore if the mod is
+ activated when activemapper is imported
+
+ .. change::
+ :tags:
+ :tickets:
+
+ small fix to URL regexp to allow filenames with '@' in them
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixes to Session expunge/update/etc...needs more cleanup.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ select_table mappers *still* werent always compiling
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed up Boolean datatype
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added count()/count_by() to list of methods proxied by assignmapper;
+ this also adds them to activemapper
+
+ .. change::
+ :tags:
+ :tickets:
+
+ connection exceptions wrapped in DBAPIError
+
+ .. change::
+ :tags:
+ :tickets:
+
+ ActiveMapper now supports autoloading column definitions from the
+ database if you supply a __autoload__ = True attribute in your
+ mapping inner-class. Currently this does not support reflecting
+ any relationships.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ deferred column load could screw up the connection status in
+ a flush() under some circumstances, this was fixed
+
+ .. change::
+ :tags:
+ :tickets:
+
+ expunge() was not working with cascade, fixed.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ potential endless loop in cascading operations fixed.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "synonym()" function, applied to properties to have a
+ propname the same as another, for the purposes of overriding props
+ and allowing the original propname to be accessible in select_by().
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to typing in clause construction which specifically helps
+ type issues with polymorphic_union (CAST/ColumnClause propagates
+ its type to proxy columns)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ mapper compilation work ongoing, someday it'll work....moved
+ around the initialization of MapperProperty objects to be after
+ all mappers are created to better handle circular compilations.
+ do_init() method is called on all properties now which are more
+ aware of their "inherited" status if so.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ eager loads explicitly disallowed on self-referential relationships, or
+ relationships to an inheriting mapper (which is also self-referential)
+
+ .. change::
+ :tags:
+ :tickets: 244
+
+ reduced bind param size in query._get to appease the picky oracle
+
+ .. change::
+ :tags:
+ :tickets: 234
+
+ added 'checkfirst' argument to table.create()/table.drop(), as
+ well as table.exists()
+
+ .. change::
+ :tags:
+ :tickets: 245
+
+ some other ongoing fixes to inheritance
+
+ .. change::
+ :tags:
+ :tickets:
+
+ attribute/backref/orphan/history-tracking tweaks as usual...
+
+.. changelog::
+ :version: 0.2.5
+ :released: Sat Jul 08 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed endless loop bug in select_by(), if the traversal hit
+ two mappers that referenced each other
+
+ .. change::
+ :tags:
+ :tickets:
+
+ upgraded all unittests to insert './lib/' into sys.path,
+ working around new setuptools PYTHONPATH-killing behavior
+
+ .. change::
+ :tags:
+ :tickets:
+
+ further fixes with attributes/dependencies/etc....
+
+ .. change::
+ :tags:
+ :tickets:
+
+ improved error handling for when DynamicMetaData is not connected
+
+ .. change::
+ :tags:
+ :tickets:
+
+ MS-SQL support largely working (tested with pymssql)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ ordering of UPDATE and DELETE statements within groups is now
+ in order of primary key values, for more deterministic ordering
+
+ .. change::
+ :tags:
+ :tickets:
+
+ after_insert/delete/update mapper extensions now called per object,
+ not per-object-per-table
+
+ .. change::
+ :tags:
+ :tickets:
+
+ further fixes/refactorings to mapper compilation
+
+.. changelog::
+ :version: 0.2.4
+ :released: Tue Jun 27 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ try/except when the mapper sets init.__name__ on a mapped class,
+ supports python 2.3
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed bug where threadlocal engine would still autocommit
+ despite a transaction in progress
+
+ .. change::
+ :tags:
+ :tickets:
+
+ lazy load and deferred load operations require the parent object
+ to be in a Session to do the operation; whereas before the operation
+ would just return a blank list or None, it now raises an exception.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Session.update() is slightly more lenient if the session to which
+ the given object was formerly attached to was garbage collected;
+ otherwise still requires you explicitly remove the instance from
+ the previous Session.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixes to mapper compilation, checking for more error conditions
+
+ .. change::
+ :tags:
+ :tickets:
+
+ small fix to eager loading combined with ordering/limit/offset
+
+ .. change::
+ :tags:
+ :tickets: 206
+
+ utterly remarkable: added a single space between 'CREATE TABLE'
+ and '(<the rest of it>' since *thats how MySQL indicates a non-
+ reserved word tablename.....*
+
+ .. change::
+ :tags:
+ :tickets:
+
+ more fixes to inheritance, related to many-to-many relations
+ properly saving
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed bug when specifying explicit module to mysql dialect
+
+ .. change::
+ :tags:
+ :tickets:
+
+ when QueuePool times out it raises a TimeoutError instead of
+ erroneously making another connection
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Queue.Queue usage in pool has been replaced with a locally
+ modified version (works in py2.3/2.4!) that uses a threading.RLock
+ for a mutex. this is to fix a reported case where a ConnectionFairy's
+ __del__() method got called within the Queue's get() method, which
+ then returns its connection to the Queue via the the put() method,
+ causing a reentrant hang unless threading.RLock is used.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ postgres will not place SERIAL keyword on a primary key column
+ if it has a foreign key constraint
+
+ .. change::
+ :tags:
+ :tickets: 221
+
+ cursor() method on ConnectionFairy allows db-specific extension
+ arguments to be propagated
+
+ .. change::
+ :tags:
+ :tickets: 225
+
+ lazy load bind params properly propagate column type
+
+ .. change::
+ :tags:
+ :tickets:
+
+ new MySQL types: MSEnum, MSTinyText, MSMediumText, MSLongText, etc.
+ more support for MS-specific length/precision params in numeric types
+ patch courtesy Mike Bernson
+
+ .. change::
+ :tags:
+ :tickets: 224
+
+ some fixes to connection pool invalidate()
+
+.. changelog::
+ :version: 0.2.3
+ :released: Sat Jun 17 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to mapper compilation to be deferred. this allows mappers
+ to be constructed in any order, and their relationships to each
+ other are compiled when the mappers are first used.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed a pretty big speed bottleneck in cascading behavior particularly
+ when backrefs were in use
+
+ .. change::
+ :tags:
+ :tickets:
+
+ the attribute instrumentation module has been completely rewritten; its
+ now a large degree simpler and clearer, slightly faster. the "history"
+ of an attribute is no longer micromanaged with each change and is
+ instead part of a "CommittedState" object created when the
+ instance is first loaded. HistoryArraySet is gone, the behavior of
+ list attributes is now more open ended (i.e. theyre not sets anymore).
+
+ .. change::
+ :tags:
+ :tickets:
+
+ py2.4 "set" construct used internally, falls back to sets.Set when
+ "set" not available/ordering is needed.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to transaction control, so that repeated rollback() calls
+ dont fail (was failing pretty badly when flush() would raise
+ an exception in a larger try/except transaction block)
+
+ .. change::
+ :tags:
+ :tickets: 151
+
+ "foreignkey" argument to relation() can also be a list. fixed
+ auto-foreignkey detection
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed bug where tables with schema names werent getting indexed in
+ the MetaData object properly
+
+ .. change::
+ :tags:
+ :tickets: 207
+
+ fixed bug where Column with redefined "key" property wasnt getting
+ type conversion happening in the ResultProxy
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed 'port' attribute of URL to be an integer if present
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed old bug where if a many-to-many table mapped as "secondary"
+ had extra columns, delete operations didnt work
+
+ .. change::
+ :tags:
+ :tickets:
+
+ bugfixes for mapping against UNION queries
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed incorrect exception class thrown when no DB driver present
+
+ .. change::
+ :tags:
+ :tickets: 138
+
+ added NonExistentTable exception thrown when reflecting a table
+ that doesnt exist
+
+ .. change::
+ :tags:
+ :tickets:
+
+ small fix to ActiveMapper regarding one-to-one backrefs, other
+ refactorings
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overridden constructor in mapped classes gets __name__ and
+ __doc__ from the original class
+
+ .. change::
+ :tags:
+ :tickets: 200
+
+ fixed small bug in selectresult.py regarding mapper extension
+
+ .. change::
+ :tags:
+ :tickets:
+
+ small tweak to cascade_mappers, not very strongly supported
+ function at the moment
+
+ .. change::
+ :tags:
+ :tickets: 202
+
+ some fixes to between(), column.between() to propagate typing
+ information better
+
+ .. change::
+ :tags:
+ :tickets: 203
+
+ if an object fails to be constructed, is not added to the
+ session
+
+ .. change::
+ :tags:
+ :tickets:
+
+ CAST function has been made into its own clause object with
+ its own compilation function in ansicompiler; allows MySQL
+ to silently ignore most CAST calls since MySQL
+ seems to only support the standard CAST syntax with Date types.
+ MySQL-compatible CAST support for strings, ints, etc. a TODO
+
+.. changelog::
+ :version: 0.2.2
+ :released: Mon Jun 05 2006
+
+ .. change::
+ :tags:
+ :tickets: 190
+
+ big improvements to polymorphic inheritance behavior, enabling it
+ to work with adjacency list table structures
+
+ .. change::
+ :tags:
+ :tickets:
+
+ major fixes and refactorings to inheritance relationships overall,
+ more unit tests
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed "echo_pool" flag on create_engine()
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to docs, removed incorrect info that close() is unsafe to use
+ with threadlocal strategy (its totally safe !)
+
+ .. change::
+ :tags:
+ :tickets: 188
+
+ create_engine() can take URLs as string or unicode
+
+ .. change::
+ :tags:
+ :tickets:
+
+ firebird support partially completed;
+ thanks to James Ralston and Brad Clements for their efforts.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Oracle url translation was broken, fixed, will feed host/port/sid
+ into cx_oracle makedsn() if 'database' field is present, else uses
+ straight TNS name from the 'host' field
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to using unicode criterion for query.get()/query.load()
+
+ .. change::
+ :tags:
+ :tickets:
+
+ count() function on selectables now uses table primary key or
+ first column instead of "1" for criterion, also uses label "rowcount"
+ instead of "count".
+
+ .. change::
+ :tags:
+ :tickets:
+
+ got rudimental "mapping to multiple tables" functionality cleaned up,
+ more correctly documented
+
+ .. change::
+ :tags:
+ :tickets:
+
+ restored global_connect() function, attaches to a DynamicMetaData
+ instance called "default_metadata". leaving MetaData arg to Table
+ out will use the default metadata.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixes to session cascade behavior, entity_name propigation
+
+ .. change::
+ :tags:
+ :tickets:
+
+ reorganized unittests into subdirectories
+
+ .. change::
+ :tags:
+ :tickets:
+
+ more fixes to threadlocal connection nesting patterns
+
+.. changelog::
+ :version: 0.2.1
+ :released: Mon May 29 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ "pool" argument to create_engine() properly propagates
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixes to URL, raises exception if not parsed, does not pass blank
+ fields along to the DB connect string (a string such as
+ user:host@/db was breaking on postgres)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ small fixes to Mapper when it inserts and tries to get
+ new primary key values back
+
+ .. change::
+ :tags:
+ :tickets:
+
+ rewrote half of TLEngine, the ComposedSQLEngine used with
+ 'strategy="threadlocal"'. it now properly implements engine.begin()/
+ engine.commit(), which nest fully with connection.begin()/trans.commit().
+ added about six unittests.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ major "duh" in pool.Pool, forgot to put back the WeakValueDictionary.
+ unittest which was supposed to check for this was also silently missing
+ it. fixed unittest to ensure that ConnectionFairy properly falls out
+ of scope.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ placeholder dispose() method added to SingletonThreadPool, doesnt
+ do anything yet
+
+ .. change::
+ :tags:
+ :tickets:
+
+ rollback() is automatically called when an exception is raised,
+ but only if theres no transaction in process (i.e. works more like
+ autocommit).
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed exception raise in sqlite if no sqlite module present
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added extra example detail for association object doc
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Connection adds checks for already being closed
+
+.. changelog::
+ :version: 0.2.0
+ :released: Sat May 27 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to Engine system so that what was formerly the SQLEngine
+ is now a ComposedSQLEngine which consists of a variety of components,
+ including a Dialect, ConnectionProvider, etc. This impacted all the
+ db modules as well as Session and Mapper.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ create_engine now takes only RFC-1738-style strings:
+ driver://user:password@host:port/database
+
+ .. change::
+ :tags:
+ :tickets: 152
+
+ total rewrite of connection-scoping methodology, Connection objects
+ can now execute clause elements directly, added explicit "close" as
+ well as support throughout Engine/ORM to handle closing properly,
+ no longer relying upon __del__ internally to return connections
+ to the pool.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to Session interface and scoping. uses hibernate-style
+ methods, including query(class), save(), save_or_update(), etc.
+ no threadlocal scope is installed by default. Provides a binding
+ interface to specific Engines and/or Connections so that underlying
+ Schema objects do not need to be bound to an Engine. Added a basic
+ SessionTransaction object that can simplistically aggregate transactions
+ across multiple engines.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to mapper's dependency and "cascade" behavior; dependency logic
+ factored out of properties.py into a separate module "dependency.py".
+ "cascade" behavior is now explicitly controllable, proper implementation
+ of "delete", "delete-orphan", etc. dependency system can now determine at
+ flush time if a child object has a parent or not so that it makes better
+ decisions on how that child should be updated in the DB with regards to deletes.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to Schema to build upon MetaData object instead of an Engine.
+ Entire SQL/Schema system can be used with no Engines whatsoever, executed
+ solely by an explicit Connection object. the "bound" methodlogy exists via the
+ BoundMetaData for schema objects. ProxyEngine is generally not needed
+ anymore and is replaced by DynamicMetaData.
+
+ .. change::
+ :tags:
+ :tickets: 167
+
+ true polymorphic behavior implemented, fixes
+
+ .. change::
+ :tags:
+ :tickets: 147
+
+ "oid" system has been totally moved into compile-time behavior;
+ if they are used in an order_by where they are not available, the order_by
+ doesnt get compiled, fixes
+
+ .. change::
+ :tags:
+ :tickets:
+
+ overhaul to packaging; "mapping" is now "orm", "objectstore" is now
+ "session", the old "objectstore" namespace gets loaded in via the
+ "threadlocal" mod if used
+
+ .. change::
+ :tags:
+ :tickets:
+
+ mods now called in via "import <modname>". extensions favored over
+ mods as mods are globally-monkeypatching
+
+ .. change::
+ :tags:
+ :tickets: 154
+
+ fix to add_property so that it propagates properties to inheriting
+ mappers
+
+ .. change::
+ :tags:
+ :tickets:
+
+ backrefs create themselves against primary mapper of its originating
+ property, priamry/secondary join arguments can be specified to override.
+ helps their usage with polymorphic mappers
+
+ .. change::
+ :tags:
+ :tickets: 31
+
+ "table exists" function has been implemented
+
+ .. change::
+ :tags:
+ :tickets: 98
+
+ "create_all/drop_all" added to MetaData object
+
+ .. change::
+ :tags:
+ :tickets:
+
+ improvements and fixes to topological sort algorithm, as well as more
+ unit tests
+
+ .. change::
+ :tags:
+ :tickets:
+
+ tutorial page added to docs which also can be run with a custom doctest
+ runner to ensure its properly working. docs generally overhauled to
+ deal with new code patterns
+
+ .. change::
+ :tags:
+ :tickets:
+
+ many more fixes, refactorings.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ migration guide is available on the Wiki at
+ http://www.sqlalchemy.org/trac/wiki/02Migration
--- /dev/null
+
+==============
+0.3 Changelog
+==============
+
+
+.. changelog::
+ :version: 0.3.11
+ :released: Sun Oct 14 2007
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ tweak DISTINCT precedence for clauses like
+ `func.count(t.c.col.distinct())`
+
+ .. change::
+ :tags: sql
+ :tickets: 719
+
+ Fixed detection of internal '$' characters in :bind$params
+
+ .. change::
+ :tags: sql
+ :tickets: 768
+
+ dont assume join criterion consists only of column objects
+
+ .. change::
+ :tags: sql
+ :tickets: 764
+
+ adjusted operator precedence of NOT to match '==' and others, so that
+ ~(x==y) produces NOT (x=y), which is compatible with MySQL < 5.0
+ (doesn't like "NOT x=y")
+
+ .. change::
+ :tags: orm
+ :tickets: 687
+
+ added a check for joining from A->B using join(), along two
+ different m2m tables. this raises an error in 0.3 but is
+ possible in 0.4 when aliases are used.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed small exception throw bug in Session.merge()
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed bug where mapper, being linked to a join where one table had
+ no PK columns, would not detect that the joined table had no PK.
+
+ .. change::
+ :tags: orm
+ :tickets: 769
+
+ fixed bugs in determining proper sync clauses from custom inherit
+ conditions
+
+ .. change::
+ :tags: orm
+ :tickets: 813
+
+ backref remove object operation doesn't fail if the other-side
+ collection doesn't contain the item, supports noload collections
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ fixed another occasional race condition which could occur
+ when using pool with threadlocal setting
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ fixed specification of YEAR columns when generating schema
+
+ .. change::
+ :tags: mssql
+ :tickets: 679
+
+ added support for TIME columns (simulated using DATETIME)
+
+ .. change::
+ :tags: mssql
+ :tickets: 721
+
+ added support for BIGINT, MONEY, SMALLMONEY, UNIQUEIDENTIFIER and
+ SQL_VARIANT
+
+ .. change::
+ :tags: mssql
+ :tickets: 684
+
+ index names are now quoted when dropping from reflected tables
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ can now specify a DSN for PyODBC, using a URI like mssql:///?dsn=bob
+
+ .. change::
+ :tags: postgres
+ :tickets:
+
+ when reflecting tables from alternate schemas, the "default" placed upon
+ the primary key, i.e. usually a sequence name, has the "schema" name
+ unconditionally quoted, so that schema names which need quoting are fine.
+ its slightly unnecessary for schema names which don't need quoting
+ but not harmful.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ passthrough for stringified dates
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ supports_sane_rowcount() set to False due to ticket #370 (right way).
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ fixed reflection of Column's nullable property.
+
+ .. change::
+ :tags: oracle
+ :tickets: 622, 751
+
+ removed LONG_STRING, LONG_BINARY from "binary" types, so type objects
+ don't try to read their values as LOB.
+
+.. changelog::
+ :version: 0.3.10
+ :released: Fri Jul 20 2007
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ a new mutex that was added in 0.3.9 causes the pool_timeout
+ feature to fail during a race condition; threads would
+ raise TimeoutError immediately with no delay if many threads
+ push the pool into overflow at the same time. this issue has been
+ fixed.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ got connection-bound metadata to work with implicit execution
+
+ .. change::
+ :tags: sql
+ :tickets: 667
+
+ foreign key specs can have any chararcter in their identifiers
+
+ .. change::
+ :tags: sql
+ :tickets: 664
+
+ added commutativity-awareness to binary clause comparisons to
+ each other, improves ORM lazy load optimization
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ cleanup to connection-bound sessions, SessionTransaction
+
+ .. change::
+ :tags: postgres
+ :tickets: 571
+
+ fixed max identifier length (63)
+
+.. changelog::
+ :version: 0.3.9
+ :released: Sun Jul 15 2007
+
+ .. change::
+ :tags: general
+ :tickets: 607
+
+ better error message for NoSuchColumnError
+
+ .. change::
+ :tags: general
+ :tickets: 428
+
+ finally figured out how to get setuptools version in, available
+ as sqlalchemy.__version__
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ the various "engine" arguments, such as "engine", "connectable",
+ "engine_or_url", "bind_to", etc. are all present, but deprecated.
+ they all get replaced by the single term "bind". you also
+ set the "bind" of MetaData using
+ metadata.bind = <engine or connection>
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ iteration over dict association proxies is now dict-like, not
+ InstrumentedList-like (e.g. over keys instead of values)
+
+ .. change::
+ :tags: ext
+ :tickets: 597
+
+ association proxies no longer bind tightly to source collections, and are constructed with a thunk instead
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ added selectone_by() to assignmapper
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ forwards-compatibility with 0.4: added one(), first(), and
+ all() to Query. almost all Query functionality from 0.4 is
+ present in 0.3.9 for forwards-compat purposes.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ reset_joinpoint() really really works this time, promise ! lets
+ you re-join from the root:
+ query.join(['a', 'b']).filter(<crit>).reset_joinpoint().\
+ join(['a', 'c']).filter(<some other crit>).all()
+ in 0.4 all join() calls start from the "root"
+
+ .. change::
+ :tags: orm
+ :tickets: 613
+
+ added synchronization to the mapper() construction step, to avoid
+ thread collisions when pre-existing mappers are compiling in a
+ different thread
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ a warning is issued by Mapper when two primary key columns of the
+ same name are munged into a single attribute. this happens frequently
+ when mapping to joins (or inheritance).
+
+ .. change::
+ :tags: orm
+ :tickets: 598
+
+ synonym() properties are fully supported by all Query joining/
+ with_parent operations
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed very stupid bug when deleting items with many-to-many
+ uselist=False relations
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ remember all that stuff about polymorphic_union ? for
+ joined table inheritance ? Funny thing...
+ You sort of don't need it for joined table inheritance, you
+ can just string all the tables together via outerjoin().
+ The UNION still applies if concrete tables are involved,
+ though (since nothing to join them on).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ small fix to eager loading to better work with eager loads
+ to polymorphic mappers that are using a straight "outerjoin"
+ clause
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ ForeignKey to a table in a schema thats not the default schema
+ requires the schema to be explicit; i.e. ForeignKey('alt_schema.users.id')
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ MetaData can now be constructed with an engine or url as the first
+ argument, just like BoundMetaData
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ BoundMetaData is now deprecated, and MetaData is a direct substitute.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ DynamicMetaData has been renamed to ThreadLocalMetaData. the
+ DynamicMetaData name is deprecated and is an alias for ThreadLocalMetaData
+ or a regular MetaData if threadlocal=False
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ composite primary key is represented as a non-keyed set to allow for
+ composite keys consisting of cols with the same name; occurs within a
+ Join. helps inheritance scenarios formulate correct PK.
+
+ .. change::
+ :tags: sql
+ :tickets: 185
+
+ improved ability to get the "correct" and most minimal set of primary key
+ columns from a join, equating foreign keys and otherwise equated columns.
+ this is also mostly to help inheritance scenarios formulate the best
+ choice of primary key columns.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added 'bind' argument to Sequence.create()/drop(), ColumnDefault.execute()
+
+ .. change::
+ :tags: sql
+ :tickets: 650
+
+ columns can be overridden in a reflected table with a "key"
+ attribute different than the column's name, including for primary key
+ columns
+
+ .. change::
+ :tags: sql
+ :tickets: 657
+
+ fixed "ambiguous column" result detection, when dupe col names exist
+ in a result
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ some enhancements to "column targeting", the ability to match a column
+ to a "corresponding" column in another selectable. this affects mostly
+ ORM ability to map to complex joins
+
+ .. change::
+ :tags: sql
+ :tickets: 619
+
+ MetaData and all SchemaItems are safe to use with pickle. slow
+ table reflections can be dumped into a pickled file to be reused later.
+ Just reconnect the engine to the metadata after unpickling.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added a mutex to QueuePool's "overflow" calculation to prevent a race
+ condition that can bypass max_overflow
+
+ .. change::
+ :tags: sql
+ :tickets: 623
+
+ fixed grouping of compound selects to give correct results. will break
+ on sqlite in some cases, but those cases were producing incorrect
+ results anyway, sqlite doesn't support grouped compound selects
+
+ .. change::
+ :tags: sql
+ :tickets: 620
+
+ fixed precedence of operators so that parenthesis are correctly applied
+
+ .. change::
+ :tags: sql
+ :tickets: 545
+
+ calling <column>.in_() (i.e. with no arguments) will return
+ "CASE WHEN (<column> IS NULL) THEN NULL ELSE 0 END = 1)", so that
+ NULL or False is returned in all cases, rather than throwing an error
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fixed "where"/"from" criterion of select() to accept a unicode string
+ in addition to regular string - both convert to text()
+
+ .. change::
+ :tags: sql
+ :tickets: 558
+
+ added standalone distinct() function in addition to column.distinct()
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ result.last_inserted_ids() should return a list that is identically
+ sized to the primary key constraint of the table. values that were
+ "passively" created and not available via cursor.lastrowid will be None.
+
+ .. change::
+ :tags: sql
+ :tickets: 589
+
+ long-identifier detection fixed to use > rather than >= for
+ max ident length
+
+ .. change::
+ :tags: sql
+ :tickets: 593
+
+ fixed bug where selectable.corresponding_column(selectable.c.col)
+ would not return selectable.c.col, if the selectable is a join
+ of a table and another join involving the same table. messed
+ up ORM decision making
+
+ .. change::
+ :tags: sql
+ :tickets: 595
+
+ added Interval type to types.py
+
+ .. change::
+ :tags: mysql
+ :tickets: 625
+
+ fixed catching of some errors that imply a dropped connection
+
+ .. change::
+ :tags: mysql
+ :tickets: 624
+
+ fixed escaping of the modulo operator
+
+ .. change::
+ :tags: mysql
+ :tickets: 590
+
+ added 'fields' to reserved words
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ various reflection enhancement/fixes
+
+ .. change::
+ :tags: oracle
+ :tickets: 604
+
+ datetime fixes: got subsecond TIMESTAMP to work,
+ added OracleDate which supports types.Date with only year/month/day
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ added dialect flag "auto_convert_lobs", defaults to True; will cause any
+ LOB objects detected in a result set to be forced into OracleBinary
+ so that the LOB is read() automatically, if no typemap was present
+ (i.e., if a textual execute() was issued).
+
+ .. change::
+ :tags: oracle
+ :tickets: 624
+
+ mod operator '%' produces MOD
+
+ .. change::
+ :tags: oracle
+ :tickets: 542
+
+ converts cx_oracle datetime objects to Python datetime.datetime when
+ Python 2.3 used
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ fixed unicode conversion in Oracle TEXT type
+
+ .. change::
+ :tags: postgres
+ :tickets: 624
+
+ fixed escaping of the modulo operator
+
+ .. change::
+ :tags: postgres
+ :tickets: 570
+
+ added support for reflection of domains
+
+ .. change::
+ :tags: postgres
+ :tickets:
+
+ types which are missing during reflection resolve to Null type
+ instead of raising an error
+
+ .. change::
+ :tags: postgres
+ :tickets:
+
+ the fix in "schema" above fixes reflection of foreign keys from an
+ alt-schema table to a public schema table
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ rearranged dialect initialization so it has time to warn about pysqlite1
+ being too old.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ sqlite better handles datetime/date/time objects mixed and matched
+ with various Date/Time/DateTime columns
+
+ .. change::
+ :tags: sqlite
+ :tickets: 603
+
+ string PK column inserts dont get overwritten with OID
+
+ .. change::
+ :tags: mssql
+ :tickets: 634
+
+ fix port option handling for pyodbc
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ now able to reflect start and increment values for identity columns
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ preliminary support for using scope_identity() with pyodbc
+
+.. changelog::
+ :version: 0.3.8
+ :released: Sat Jun 02 2007
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ added detach() to Connection, allows underlying DBAPI connection
+ to be detached from its pool, closing on dereference/close()
+ instead of being reused by the pool.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ added invalidate() to Connection, immediately invalidates the
+ Connection and its underlying DBAPI connection.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ _Label class overrides compare_self to return its ultimate
+ object. meaning, if you say someexpr.label('foo') == 5, it
+ produces the correct "someexpr == 5".
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ _Label propagates "_hide_froms()" so that scalar selects
+ behave more properly with regards to FROM clause #574
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fix to long name generation when using oid_column as an order by
+ (oids used heavily in mapper queries)
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ significant speed improvement to ResultProxy, pre-caches
+ TypeEngine dialect implementations and saves on function calls
+ per column
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ parenthesis are applied to clauses via a new _Grouping
+ construct. uses operator precedence to more intelligently apply
+ parenthesis to clauses, provides cleaner nesting of clauses
+ (doesnt mutate clauses placed in other clauses, i.e. no 'parens'
+ flag)
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added 'modifier' keyword, works like func.<foo> except does not
+ add parenthesis. e.g. select([modifier.DISTINCT(...)]) etc.
+
+ .. change::
+ :tags: sql
+ :tickets: 578
+
+ removed "no group by's in a select thats part of a UNION"
+ restriction
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added reset_joinpoint() method to Query, moves the "join point"
+ back to the starting mapper. 0.4 will change the behavior of
+ join() to reset the "join point" in all cases so this is an
+ interim method. for forwards compatibility, ensure joins across
+ multiple relations are specified using a single join(), i.e.
+ join(['a', 'b', 'c']).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed bug in query.instances() that wouldnt handle more than
+ on additional mapper or one additional column.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ "delete-orphan" no longer implies "delete". ongoing effort to
+ separate the behavior of these two operations.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ many-to-many relationships properly set the type of bind params
+ for delete operations on the association table
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ many-to-many relationships check that the number of rows deleted
+ from the association table by a delete operation matches the
+ expected results
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ session.get() and session.load() propagate **kwargs through to
+ query
+
+ .. change::
+ :tags: orm
+ :tickets: 577
+
+ fix to polymorphic query which allows the original
+ polymorphic_union to be embedded into a correlated subquery
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fix to select_by(<propname>=<object instance>) -style joins in
+ conjunction with many-to-many relationships, bug introduced in
+ r2556
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the "primary_key" argument to mapper() is propagated to the
+ "polymorphic" mapper. primary key columns in this list get
+ normalized to that of the mapper's local table.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ restored logging of "lazy loading clause" under
+ sa.orm.strategies logger, got removed in 0.3.7
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ improved support for eagerloading of properties off of mappers
+ that are mapped to select() statements; i.e. eagerloader is
+ better at locating the correct selectable with which to attach
+ its LEFT OUTER JOIN.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Nearly all MySQL column types are now supported for declaration
+ and reflection. Added NCHAR, NVARCHAR, VARBINARY, TINYBLOB,
+ LONGBLOB, YEAR
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ The sqltypes.Binary passthrough now always builds a BLOB,
+ avoiding problems with very old database versions
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ support for column-level CHARACTER SET and COLLATE declarations,
+ as well as ASCII, UNICODE, NATIONAL and BINARY shorthand.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ set max identifier length to 31
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ supports_sane_rowcount() set to False due to ticket #370.
+ versioned_id_col feature wont work in FB.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ some execution fixes
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ new association proxy implementation, implementing complete
+ proxies to list, dict and set-based relation collections
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ added orderinglist, a custom list class that synchronizes an
+ object attribute with that object's position in the list
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ small fix to SelectResultsExt to not bypass itself during
+ select().
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ added filter(), filter_by() to assignmapper
+
+.. changelog::
+ :version: 0.3.7
+ :released: Sun Apr 29 2007
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ warnings module used for issuing warnings (instead of logging)
+
+ .. change::
+ :tags: engines
+ :tickets: 480
+
+ cleanup of DBAPI import strategies across all engines
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ refactoring of engine internals which reduces complexity,
+ number of codepaths; places more state inside of ExecutionContext
+ to allow more dialect control of cursor handling, result sets.
+ ResultProxy totally refactored and also has two versions of
+ "buffered" result sets used for different purposes.
+
+ .. change::
+ :tags: engines
+ :tickets: 514
+
+ server side cursor support fully functional in postgres.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ improved framework for auto-invalidation of connections that have
+ lost their underlying database, via dialect-specific detection
+ of exceptions corresponding to that database's disconnect
+ related error messages. Additionally, when a "connection no
+ longer open" condition is detected, the entire connection pool
+ is discarded and replaced with a new instance. #516
+
+ .. change::
+ :tags: engines
+ :tickets: 521
+
+ the dialects within sqlalchemy.databases become a setuptools
+ entry points. loading the built-in database dialects works the
+ same as always, but if none found will fall back to trying
+ pkg_resources to load an external module
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Engine contains a "url" attribute referencing the url.URL object
+ used by create_engine().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ keys() of result set columns are not lowercased, come back
+ exactly as they're expressed in cursor.description. note this
+ causes colnames to be all caps in oracle.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ preliminary support for unicode table names, column names and
+ SQL statements added, for databases which can support them.
+ Works with sqlite and postgres so far. Mysql *mostly* works
+ except the has_table() function does not work. Reflection
+ works too.
+
+ .. change::
+ :tags: sql
+ :tickets: 522
+
+ the Unicode type is now a direct subclass of String, which now
+ contains all the "convert_unicode" logic. This helps the variety
+ of unicode situations that occur in db's such as MS-SQL to be
+ better handled and allows subclassing of the Unicode datatype.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ ClauseElements can be used in in_() clauses now, such as bind
+ parameters, etc. #476
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ reverse operators implemented for `CompareMixin` elements,
+ allows expressions like "5 + somecolumn" etc. #474
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the "where" criterion of an update() and delete() now correlates
+ embedded select() statements against the table being updated or
+ deleted. this works the same as nested select() statement
+ correlation, and can be disabled via the correlate=False flag on
+ the embedded select().
+
+ .. change::
+ :tags: sql
+ :tickets: 512
+
+ column labels are now generated in the compilation phase, which
+ means their lengths are dialect-dependent. So on oracle a label
+ that gets truncated to 30 chars will go out to 63 characters
+ on postgres. Also, the true labelname is always attached as the
+ accessor on the parent Selectable so theres no need to be aware
+ of the "truncated" label names.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ column label and bind param "truncation" also generate
+ deterministic names now, based on their ordering within the
+ full statement being compiled. this means the same statement
+ will produce the same string across application restarts and
+ allowing DB query plan caching to work better.
+
+ .. change::
+ :tags: sql
+ :tickets: 513
+
+ the "mini" column labels generated when using subqueries, which
+ are to work around glitchy SQLite behavior that doesnt understand
+ "foo.id" as equivalent to "id", are now only generated in the case
+ that those named columns are selected from (part of)
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the label() method on ColumnElement will properly propagate the
+ TypeEngine of the base element out to the label, including a label()
+ created from a scalar=True select() statement.
+
+ .. change::
+ :tags: sql
+ :tickets: 513
+
+ MS-SQL better detects when a query is a subquery and knows not to
+ generate ORDER BY phrases for those
+
+ .. change::
+ :tags: sql
+ :tickets: 505
+
+ fix for fetchmany() "size" argument being positional in most
+ dbapis
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ sending None as an argument to func.<something> will produce
+ an argument of NULL
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ query strings in unicode URLs get keys encoded to ascii
+ for **kwargs compat
+
+ .. change::
+ :tags: sql
+ :tickets: 523
+
+ slight tweak to raw execute() change to also support tuples
+ for positional parameters, not just lists
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fix to case() construct to propagate the type of the first
+ WHEN condition as the return type of the case statement
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed critical issue when, after options(eagerload()) is used,
+ the mapper would then always apply query "wrapping" behavior
+ for all subsequent LIMIT/OFFSET/DISTINCT queries, even if no
+ eager loading was applied on those subsequent queries.
+
+ .. change::
+ :tags: orm
+ :tickets: 541
+
+ added query.with_parent(someinstance) method. searches for
+ target instance using lazy join criterion from parent instance.
+ takes optional string "property" to isolate the desired relation.
+ also adds static Query.query_from_parent(instance, property)
+ version.
+
+ .. change::
+ :tags: orm
+ :tickets: 554
+
+ improved query.XXX_by(someprop=someinstance) querying to use
+ similar methodology to with_parent, i.e. using the "lazy" clause
+ which prevents adding the remote instance's table to the SQL,
+ thereby making more complex conditions possible
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added generative versions of aggregates, i.e. sum(), avg(), etc.
+ to query. used via query.apply_max(), apply_sum(), etc.
+ #552
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fix to using distinct() or distinct=True in combination with
+ join() and similar
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ corresponding to label/bindparam name generation, eager loaders
+ generate deterministic names for the aliases they create using
+ md5 hashes.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ improved/fixed custom collection classes when giving it "set"/
+ "sets.Set" classes or subclasses (was still looking for append()
+ methods on them during lazy loads)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ restored old "column_property()" ORM function (used to be called
+ "column()") to force any column expression to be added as a property
+ on a mapper, particularly those that aren't present in the mapped
+ selectable. this allows "scalar expressions" of any kind to be
+ added as relations (though they have issues with eager loads).
+
+ .. change::
+ :tags: orm
+ :tickets: 533
+
+ fix to many-to-many relationships targeting polymorphic mappers
+
+ .. change::
+ :tags: orm
+ :tickets: 543
+
+ making progress with session.merge() as well as combining its
+ usage with entity_name
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the usual adjustments to relationships between inheriting mappers,
+ in this case establishing relation()s to subclass mappers where
+ the join conditions come from the superclass' table
+
+ .. change::
+ :tags: informix
+ :tickets:
+
+ informix support added ! courtesy James Zhang, who put a ton
+ of effort in.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ removed silly behavior where sqlite would reflect UNIQUE indexes
+ as part of the primary key (?!)
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ small fix to allow successive compiles of the same SELECT object
+ which features LIMIT/OFFSET. oracle dialect needs to modify
+ the object to have ROW_NUMBER OVER and wasn't performing
+ the full series of steps on successive compiles.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ support for SSL arguments given as inline within URL query string,
+ prefixed with "ssl_", courtesy terjeros@gmail.com.
+
+ .. change::
+ :tags: <schemaname>, mysql
+ :tickets:
+
+ mysql uses "DESCRIBE.<tablename>", catching exceptions
+ if table doesnt exist, in order to determine if a table exists.
+ this supports unicode table names as well as schema names. tested
+ with MySQL5 but should work with 4.1 series as well. (#557)
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ big fix to AssociationProxy so that multiple AssociationProxy
+ objects can be associated with a single association collection.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ assign_mapper names methods according to their keys (i.e. __name__)
+ #551
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ pyodbc is now the preferred DB-API for MSSQL, and if no module is
+ specifically requested, will be loaded first on a module probe.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ The @@SCOPE_IDENTITY is now used instead of @@IDENTITY. This
+ behavior may be overridden with the engine_connect
+ "use_scope_identity" keyword parameter, which may also be specified
+ in the dburi.
+
+.. changelog::
+ :version: 0.3.6
+ :released: Fri Mar 23 2007
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ bindparam() names are now repeatable! specify two
+ distinct bindparam()s with the same name in a single statement,
+ and the key will be shared. proper positional/named args translate
+ at compile time. for the old behavior of "aliasing" bind parameters
+ with conflicting names, specify "unique=True" - this option is
+ still used internally for all the auto-genererated (value-based)
+ bind parameters.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ slightly better support for bind params as column clauses, either
+ via bindparam() or via literal(), i.e. select([literal('foo')])
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ MetaData can bind to an engine either via "url" or "engine" kwargs
+ to constructor, or by using connect() method. BoundMetaData is
+ identical to MetaData except engine_or_url param is required.
+ DynamicMetaData is the same and provides thread-local connections be
+ default.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ exists() becomes useable as a standalone selectable, not just in a
+ WHERE clause, i.e. exists([columns], criterion).select()
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ correlated subqueries work inside of ORDER BY, GROUP BY
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fixed function execution with explicit connections, i.e.
+ conn.execute(func.dosomething())
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ use_labels flag on select() wont auto-create labels for literal text
+ column elements, since we can make no assumptions about the text. to
+ create labels for literal columns, you can say "somecol AS
+ somelabel", or use literal_column("somecol").label("somelabel")
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ quoting wont occur for literal columns when they are "proxied" into
+ the column collection for their selectable (is_literal flag is
+ propagated). literal columns are specified via
+ literal_column("somestring").
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added "fold_equivalents" boolean argument to Join.select(), which
+ removes 'duplicate' columns from the resulting column clause that
+ are known to be equivalent based on the join condition. this is of
+ great usage when constructing subqueries of joins which Postgres
+ complains about if duplicate column names are present.
+
+ .. change::
+ :tags: sql
+ :tickets: 503
+
+ fixed use_alter flag on ForeignKeyConstraint
+
+ .. change::
+ :tags: sql
+ :tickets: 506
+
+ fixed usage of 2.4-only "reversed" in topological.py
+
+ .. change::
+ :tags: sql
+ :tickets: 501
+
+ for hackers, refactored the "visitor" system of ClauseElement and
+ SchemaItem so that the traversal of items is controlled by the
+ ClauseVisitor itself, using the method visitor.traverse(item).
+ accept_visitor() methods can still be called directly but will not
+ do any traversal of child items. ClauseElement/SchemaItem now have a
+ configurable get_children() method to return the collection of child
+ elements for each parent object. This allows the full traversal of
+ items to be clear and unambiguous (as well as loggable), with an
+ easy method of limiting a traversal (just pass flags which are
+ picked up by appropriate get_children() methods).
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the "else_" parameter to the case statement now properly works when
+ set to zero.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the full featureset of the SelectResults extension has been merged
+ into a new set of methods available off of Query. These methods
+ all provide "generative" behavior, whereby the Query is copied
+ and a new one returned with additional criterion added.
+ The new methods include:
+
+ filter() - applies select criterion to the query
+ filter_by() - applies "by"-style criterion to the query
+ avg() - return the avg() function on the given column
+ join() - join to a property (or across a list of properties)
+ outerjoin() - like join() but uses LEFT OUTER JOIN
+ limit()/offset() - apply LIMIT/OFFSET
+ range-based access which applies limit/offset:
+ session.query(Foo)[3:5]
+ distinct() - apply DISTINCT
+ list() - evaluate the criterion and return results
+
+ no incompatible changes have been made to Query's API and no methods
+ have been deprecated. Existing methods like select(), select_by(),
+ get(), get_by() all execute the query at once and return results
+ like they always did. join_to()/join_via() are still there although
+ the generative join()/outerjoin() methods are easier to use.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the return value for multiple mappers used with instances() now
+ returns a cartesian product of the requested list of mappers,
+ represented as a list of tuples. this corresponds to the documented
+ behavior. So that instances match up properly, the "uniquing" is
+ disabled when this feature is used.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query has add_entity() and add_column() generative methods. these
+ will add the given mapper/class or ColumnElement to the query at
+ compile time, and apply them to the instances() method. the user is
+ responsible for constructing reasonable join conditions (otherwise
+ you can get full cartesian products). result set is the list of
+ tuples, non-uniqued.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ strings and columns can also be sent to the *args of instances()
+ where those exact result columns will be part of the result tuples.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ a full select() construct can be passed to query.select() (which
+ worked anyway), but also query.selectfirst(), query.selectone()
+ which will be used as is (i.e. no query is compiled). works
+ similarly to sending the results to instances().
+
+ .. change::
+ :tags: orm
+ :tickets: 495
+
+ eager loading will not "aliasize" "order by" clauses that were
+ placed in the select statement by something other than the eager
+ loader itself, to fix possibility of dupe columns as illustrated in. however, this means you have to be more careful with
+ the columns placed in the "order by" of Query.select(), that you
+ have explicitly named them in your criterion (i.e. you cant rely on
+ the eager loader adding them in for you)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added a handy multi-use "identity_key()" method to Session, allowing
+ the generation of identity keys for primary key values, instances,
+ and rows, courtesy Daniel Miller
+
+ .. change::
+ :tags: orm
+ :tickets: 249
+
+ many-to-many table will be properly handled even for operations that
+ occur on the "backref" side of the operation
+
+ .. change::
+ :tags: orm
+ :tickets: 492
+
+ added "refresh-expire" cascade. allows refresh() and
+ expire() calls to propagate along relationships.
+
+ .. change::
+ :tags: orm
+ :tickets: 493
+
+ more fixes to polymorphic relations, involving proper lazy-clause
+ generation on many-to-one relationships to polymorphic mappers. also fixes to detection of "direction", more specific
+ targeting of columns that belong to the polymorphic union vs. those
+ that dont.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ some fixes to relationship calcs when using "viewonly=True" to pull
+ in other tables into the join condition which arent parent of the
+ relationship's parent/child mappings
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ flush fixes on cyclical-referential relationships that contain
+ references to other instances outside of the cyclical chain, when
+ some of the objects in the cycle are not actually part of the flush
+
+ .. change::
+ :tags: orm
+ :tickets: 500
+
+ put an aggressive check for "flushing object A with a collection of
+ B's, but you put a C in the collection" error condition - **even if
+ C is a subclass of B**, unless B's mapper loads polymorphically.
+ Otherwise, the collection will later load a "B" which should be a
+ "C" (since its not polymorphic) which breaks in bi-directional
+ relationships (i.e. C has its A, but A's backref will lazyload it as
+ a different instance of type "B") This check is going
+ to bite some of you who do this without issues, so the error message
+ will also document a flag "enable_typechecks=False" to disable this
+ checking. But be aware that bi-directional relationships in
+ particular become fragile without this check.
+
+ .. change::
+ :tags: extensions
+ :tickets: 472
+
+ options() method on SelectResults now implemented "generatively"
+ like the rest of the SelectResults methods. But
+ you're going to just use Query now anyway.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ query() method is added by assignmapper. this helps with
+ navigating to all the new generative methods on Query.
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ removed seconds input on DATE column types (probably
+ should remove the time altogether)
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ null values in float fields no longer raise errors
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ LIMIT with OFFSET now raises an error (MS-SQL has no OFFSET support)
+
+ .. change::
+ :tags: ms-sql
+ :tickets: 509
+
+ added an facility to use the MSSQL type VARCHAR(max) instead of TEXT
+ for large unsized string fields. Use the new "text_as_varchar" to
+ turn it on.
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ ORDER BY clauses without a LIMIT are now stripped in subqueries, as
+ MS-SQL forbids this usage
+
+ .. change::
+ :tags: ms-sql
+ :tickets: 480
+
+ cleanup of module importing code; specifiable DB-API module; more
+ explicit ordering of module preferences.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ got binary working for any size input ! cx_oracle works fine,
+ it was my fault as BINARY was being passed and not BLOB for
+ setinputsizes (also unit tests werent even setting input sizes).
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ also fixed CLOB read/write on a separate changeset.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ auto_setinputsizes defaults to True for Oracle, fixed cases where
+ it improperly propagated bad types.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ added a catchall **kwargs to MSString, to help reflection of
+ obscure types (like "varchar() binary" in MS 4.0)
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ added explicit MSTimeStamp type which takes effect when using
+ types.TIMESTAMP.
+
+.. changelog::
+ :version: 0.3.5
+ :released: Thu Feb 22 2007
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the value of "case_sensitive" defaults to True now, regardless of the
+ casing of the identifier, unless specifically set to False. this is
+ because the object might be label'ed as something else which does
+ contain mixed case, and propigating "case_sensitive=False" breaks that.
+ Other fixes to quoting when using labels and "fake" column objects
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added a "supports_execution()" method to ClauseElement, so that
+ individual kinds of clauses can express if they are appropriate for
+ executing...such as, you can execute a "select", but not a "Table" or a
+ "Join".
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fixed argument passing to straight textual execute() on engine,
+ connection. can handle *args or a list instance for positional, **kwargs
+ or a dict instance for named args, or a list of list or dicts to invoke
+ executemany()
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ small fix to BoundMetaData to accept unicode or string URLs
+
+ .. change::
+ :tags: sql
+ :tickets: 466
+
+ fixed named PrimaryKeyConstraint generation courtesy
+ andrija at gmail
+
+ .. change::
+ :tags: sql
+ :tickets: 464
+
+ fixed generation of CHECK constraints on columns
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fixes to tometadata() operation to propagate Constraints at column and
+ table level
+
+ .. change::
+ :tags: oracle
+ :tickets: 436
+
+ when returning "rowid" as the ORDER BY column or in use with ROW_NUMBER
+ OVER, oracle dialect checks the selectable its being applied to and will
+ switch to table PK if not applicable, i.e. for a UNION. checking for
+ DISTINCT, GROUP BY (other places that rowid is invalid) still a TODO.
+ allows polymorphic mappings to function.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ sequences on a non-pk column will properly fire off on INSERT
+
+ .. change::
+ :tags: oracle
+ :tickets: 435
+
+ added PrefetchingResultProxy support to pre-fetch LOB columns when they
+ are known to be present, fixes
+
+ .. change::
+ :tags: oracle
+ :tickets: 379
+
+ implemented reflection of tables based on synonyms, including across
+ dblinks
+
+ .. change::
+ :tags: oracle
+ :tickets: 363
+
+ issues a log warning when a related table cant be reflected due to
+ certain permission errors
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ fix to reflection on older DB's that might return array() type for
+ "show variables like" statements
+
+ .. change::
+ :tags: postgres
+ :tickets: 442
+
+ better reflection of sequences for alternate-schema Tables
+
+ .. change::
+ :tags: postgres
+ :tickets:
+
+ sequences on a non-pk column will properly fire off on INSERT
+
+ .. change::
+ :tags: postgres
+ :tickets: 460, 444
+
+ added PGInterval type, PGInet type
+
+ .. change::
+ :tags: mssql
+ :tickets: 419
+
+ preliminary support for pyodbc (Yay!)
+
+ .. change::
+ :tags: mssql
+ :tickets: 298
+
+ better support for NVARCHAR types added
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ fix for commit logic on pymssql
+
+ .. change::
+ :tags: mssql
+ :tickets: 456
+
+ fix for query.get() with schema
+
+ .. change::
+ :tags: mssql
+ :tickets: 473
+
+ fix for non-integer relationships
+
+ .. change::
+ :tags: mssql
+ :tickets: 419
+
+ DB-API module now selectable at run-time
+
+ .. change::
+ :tags: tickets:422, 481, 415, mssql
+ :tickets:
+
+ now passes many more unit tests
+
+ .. change::
+ :tags: mssql
+ :tickets: 479
+
+ better unittest compatibility with ANSI functions
+
+ .. change::
+ :tags: mssql
+ :tickets: 415
+
+ improved support for implicit sequence PK columns with auto-insert
+
+ .. change::
+ :tags: mssql
+ :tickets: 371
+
+ fix for blank password in adodbapi
+
+ .. change::
+ :tags: mssql
+ :tickets: 481
+
+ fixes to get unit tests working with pyodbc
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ fix to auto_identity_insert on db-url query
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ added query_timeout to db-url query parms. currently works only for
+ pymssql
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ tested with pymssql 0.8.0 (which is now LGPL)
+
+ .. change::
+ :tags: orm, bugs
+ :tickets: 441, 448, 439
+
+ another refactoring to relationship calculation. Allows more accurate
+ ORM behavior with relationships from/to/between mappers, particularly
+ polymorphic mappers, also their usage with Query, SelectResults. tickets
+ include,,.
+
+ .. change::
+ :tags: orm, bugs
+ :tickets:
+
+ removed deprecated method of specifying custom collections on classes;
+ you must now use the "collection_class" option. the old way was
+ beginning to produce conflicts when people used assign_mapper(), which
+ now patches an "options" method, in conjunction with a relationship
+ named "options". (relationships take precedence over monkeypatched
+ assign_mapper methods).
+
+ .. change::
+ :tags: orm, bugs
+ :tickets: 454
+
+ extension() query option propagates to Mapper._instance() method so that
+ all loading-related methods get called
+
+ .. change::
+ :tags: orm, bugs
+ :tickets:
+
+ eager relation to an inheriting mapper wont fail if no rows returned for
+ the relationship.
+
+ .. change::
+ :tags: orm, bugs
+ :tickets: 486
+
+ eager relation loading bug fixed for eager relation on multiple
+ descendant classes
+
+ .. change::
+ :tags: orm, bugs
+ :tickets: 423
+
+ fix for very large topological sorts, courtesy ants.aasma at gmail
+
+ .. change::
+ :tags: orm, bugs
+ :tickets:
+
+ eager loading is slightly more strict about detecting "self-referential"
+ relationships, specifically between polymorphic mappers. this results in
+ an "eager degrade" to lazy loading.
+
+ .. change::
+ :tags: orm, bugs
+ :tickets: 449
+
+ improved support for complex queries embedded into "where" criterion for
+ query.select()
+
+ .. change::
+ :tags: orm, bugs
+ :tickets: 485
+
+ mapper options like eagerload(), lazyload(), deferred(), will work for
+ "synonym()" relationships
+
+ .. change::
+ :tags: orm, bugs
+ :tickets: 445
+
+ fixed bug where cascade operations incorrectly included deleted
+ collection items in the cascade
+
+ .. change::
+ :tags: orm, bugs
+ :tickets: 478
+
+ fixed relationship deletion error when one-to-many child item is moved
+ to a new parent in a single unit of work
+
+ .. change::
+ :tags: orm, bugs
+ :tickets:
+
+ fixed relationship deletion error where parent/child with a single
+ column as PK/FK on the child would raise a "blank out the primary key"
+ error, if manually deleted or "delete" cascade without "delete-orphan"
+ was used
+
+ .. change::
+ :tags: orm, bugs
+ :tickets:
+
+ fix to deferred so that load operation doesnt mistakenly occur when only
+ PK col attributes are set
+
+ .. change::
+ :tags: orm, enhancements
+ :tickets: 385
+
+ implemented foreign_keys argument to mapper. use in
+ conjunction with primaryjoin/secondaryjoin arguments to specify/override
+ foreign keys defined on the Table instance.
+
+ .. change::
+ :tags: orm, enhancements
+ :tickets:
+
+ contains_eager('foo') automatically implies eagerload('foo')
+
+ .. change::
+ :tags: orm, enhancements
+ :tickets:
+
+ added "alias" argument to contains_eager(). use it to specify the string
+ name or Alias instance of an alias used in the query for the eagerly
+ loaded child items. easier to use than "decorator"
+
+ .. change::
+ :tags: orm, enhancements
+ :tickets:
+
+ added "contains_alias()" option for result set mapping to an alias of
+ the mapped table
+
+ .. change::
+ :tags: orm, enhancements
+ :tickets: 468
+
+ added support for py2.5 "with" statement with SessionTransaction
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ added distinct() method to SelectResults. generally should only make a
+ difference when using count().
+
+ .. change::
+ :tags: extensions
+ :tickets: 472
+
+ added options() method to SelectResults, equivalent to query.options()
+
+ .. change::
+ :tags: extensions
+ :tickets: 462
+
+ added optional __table_opts__ dictionary to ActiveMapper, will send kw
+ options to Table objects
+
+ .. change::
+ :tags: extensions
+ :tickets: 467
+
+ added selectfirst(), selectfirst_by() to assign_mapper
+
+.. changelog::
+ :version: 0.3.4
+ :released: Tue Jan 23 2007
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ global "insure"->"ensure" change. in US english "insure" is actually
+ largely interchangeable with "ensure" (so says the dictionary), so I'm not
+ completely illiterate, but its definitely sub-optimal to "ensure" which is
+ non-ambiguous.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added "fetchmany()" support to ResultProxy
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added support for column "key" attribute to be useable in
+ row[<key>]/row.<key>
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ changed "BooleanExpression" to subclass from "BinaryExpression", so that
+ boolean expressions can also follow column-clause behaviors (i.e. label(),
+ etc).
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ trailing underscores are trimmed from func.<xxx> calls, such as func.if_()
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fix to correlation of subqueries when the column list of the select
+ statement is constructed with individual calls to append_column(); this
+ fixes an ORM bug whereby nested select statements were not getting
+ correlated with the main select generated by the Query object.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ another fix to subquery correlation so that a subquery which has only one
+ FROM element will *not* correlate that single element, since at least one
+ FROM element is required in a query.
+
+ .. change::
+ :tags: sql
+ :tickets: 414
+
+ default "timezone" setting is now False. this corresponds to Python's
+ datetime behavior as well as Postgres' timestamp/time types (which is the
+ only timezone-sensitive dialect at the moment)
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the "op()" function is now treated as an "operation", rather than a
+ "comparison". the difference is, an operation produces a BinaryExpression
+ from which further operations can occur whereas comparison produces the
+ more restrictive BooleanExpression
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ trying to redefine a reflected primary key column as non-primary key raises
+ an error
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ type system slightly modified to support TypeDecorators that can be
+ overridden by the dialect (ok, thats not very clear, it allows the mssql
+ tweak below to be possible)
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ added an NVarchar type (produces NVARCHAR), also MSUnicode which provides
+ Unicode-translation for the NVarchar regardless of dialect convert_unicode
+ setting.
+
+ .. change::
+ :tags: postgres
+ :tickets: 424
+
+ fix to the initial checkfirst for tables to take current schema into
+ account
+
+ .. change::
+ :tags: postgres
+ :tickets:
+
+ postgres has an optional "server_side_cursors=True" flag which will utilize
+ server side cursors. these are appropriate for fetching only partial
+ results and are necessary for working with very large unbounded result
+ sets. While we'd like this to be the default behavior, different
+ environments seem to have different results and the causes have not been
+ isolated so we are leaving the feature off by default for now. Uses an
+ apparently undocumented psycopg2 behavior recently discovered on the
+ psycopg mailing list.
+
+ .. change::
+ :tags: postgres
+ :tickets:
+
+ added "BIGSERIAL" support for postgres table with
+ PGBigInteger/autoincrement
+
+ .. change::
+ :tags: postgres
+ :tickets: 402
+
+ fixes to postgres reflection to better handle when schema names are
+ present; thanks to jason (at) ncsmags.com
+
+ .. change::
+ :tags: mysql
+ :tickets: 420
+
+ mysql is inconsistent with what kinds of quotes it uses in foreign keys
+ during a SHOW CREATE TABLE, reflection updated to accomodate for all three
+ styles
+
+ .. change::
+ :tags: mysql
+ :tickets: 418
+
+ mysql table create options work on a generic passthru now, i.e. Table(...,
+ mysql_engine='InnoDB', mysql_collate="latin1_german2_ci",
+ mysql_auto_increment="5", mysql_<somearg>...), helps
+
+ .. change::
+ :tags: firebird
+ :tickets: 408
+
+ order of constraint creation puts primary key first before all other
+ constraints; required for firebird, not a bad idea for others
+
+ .. change::
+ :tags: firebird
+ :tickets: 409
+
+ Firebird fix to autoload multifield foreign keys
+
+ .. change::
+ :tags: firebird
+ :tickets: 409
+
+ Firebird NUMERIC type properly handles a type without precision
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ *slight* support for binary, but still need to figure out how to insert
+ reasonably large values (over 4K). requires auto_setinputsizes=True sent to
+ create_engine(), rows must be fully fetched individually, etc.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ poked the first hole in the can of worms: saying
+ query.select_by(somerelationname=someinstance) will create the join of the
+ primary key columns represented by "somerelationname"'s mapper to the
+ actual primary key in "someinstance".
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ reworked how relations interact with "polymorphic" mappers, i.e. mappers
+ that have a select_table as well as polymorphic flags. better determination
+ of proper join conditions, interaction with user- defined join conditions,
+ and support for self-referential polymorphic mappers.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ related to polymorphic mapping relations, some deeper error checking when
+ compiling relations, to detect an ambiguous "primaryjoin" in the case that
+ both sides of the relationship have foreign key references in the primary
+ join condition. also tightened down conditions used to locate "relation
+ direction", associating the "foreignkey" of the relationship with the
+ "primaryjoin"
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ a little bit of improvement to the concept of a "concrete" inheritance
+ mapping, though that concept is not well fleshed out yet (added test case
+ to support concrete mappers on top of a polymorphic base).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fix to "proxy=True" behavior on synonym()
+
+ .. change::
+ :tags: orm
+ :tickets: 427
+
+ fixed bug where delete-orphan basically didn't work with many-to-many
+ relationships, backref presence generally hid the symptom
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added a mutex to the mapper compilation step. ive been reluctant to add any
+ kind of threading anything to SA but this is one spot that its its really
+ needed since mappers are typically "global", and while their state does not
+ change during normal operation, the initial compilation step does modify
+ internal state significantly, and this step usually occurs not at
+ module-level initialization time (unless you call compile()) but at
+ first-request time
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ basic idea of "session.merge()" actually implemented. needs more testing.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added "compile_mappers()" function as a shortcut to compiling all mappers
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fix to MapperExtension create_instance so that entity_name properly
+ associated with new instance
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ speed enhancements to ORM object instantiation, eager loading of rows
+
+ .. change::
+ :tags: orm
+ :tickets: 406
+
+ invalid options sent to 'cascade' string will raise an exception
+
+ .. change::
+ :tags: orm
+ :tickets: 407
+
+ fixed bug in mapper refresh/expire whereby eager loaders didnt properly
+ re-populate item lists
+
+ .. change::
+ :tags: orm
+ :tickets: 413
+
+ fix to post_update to ensure rows are updated even for non insert/delete
+ scenarios
+
+ .. change::
+ :tags: orm
+ :tickets: 412
+
+ added an error message if you actually try to modify primary key values on
+ an entity and then flush it
+
+ .. change::
+ :tags: extensions
+ :tickets: 426
+
+ added "validate=False" argument to assign_mapper, if True will ensure that
+ only mapped attributes are named
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ assign_mapper gets "options", "instances" functions added (i.e.
+ MyClass.instances())
+
+.. changelog::
+ :version: 0.3.3
+ :released: Fri Dec 15 2006
+
+ .. change::
+ :tags:
+ :tickets:
+
+ string-based FROM clauses fixed, i.e. select(..., from_obj=["sometext"])
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixes to passive_deletes flag, lazy=None (noload) flag
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added example/docs for dealing with large collections
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added object_session() method to sqlalchemy namespace
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed QueuePool bug whereby its better able to reconnect to a database
+ that was not reachable (thanks to Sébastien Lelong), also fixed dispose()
+ method
+
+ .. change::
+ :tags:
+ :tickets: 396
+
+ patch that makes MySQL rowcount work correctly!
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to MySQL catch of 2006/2014 errors to properly re-raise OperationalError
+ exception
+
+.. changelog::
+ :version: 0.3.2
+ :released: Sun Dec 10 2006
+
+ .. change::
+ :tags:
+ :tickets: 387
+
+ major connection pool bug fixed. fixes MySQL out of sync
+ errors, will also prevent transactions getting rolled back
+ accidentally in all DBs
+
+ .. change::
+ :tags:
+ :tickets:
+
+ major speed enhancements vs. 0.3.1, to bring speed
+ back to 0.2.8 levels
+
+ .. change::
+ :tags:
+ :tickets:
+
+ made conditional dozens of debug log calls that were
+ time-intensive to generate log messages
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed bug in cascade rules whereby the entire object graph
+ could be unnecessarily cascaded on the save/update cascade
+
+ .. change::
+ :tags:
+ :tickets:
+
+ various speedups in attributes module
+
+ .. change::
+ :tags:
+ :tickets: 388
+
+ identity map in Session is by default *no longer weak referencing*.
+ to have it be weak referencing, use create_session(weak_identity_map=True)
+ fixes
+
+ .. change::
+ :tags:
+ :tickets:
+
+ MySQL detects errors 2006 (server has gone away) and 2014
+ (commands out of sync) and invalidates the connection on which it occured.
+
+ .. change::
+ :tags:
+ :tickets: 307
+
+ MySQL bool type fix:
+
+ .. change::
+ :tags:
+ :tickets: 382, 349
+
+ postgres reflection fixes:
+
+ .. change::
+ :tags:
+ :tickets: 247
+
+ added keywords for EXCEPT, INTERSECT, EXCEPT ALL, INTERSECT ALL
+
+ .. change::
+ :tags:
+ :tickets: 2110
+
+ assign_mapper in assignmapper extension returns the created mapper
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added label() function to Select class, when scalar=True is used
+ to create a scalar subquery
+ i.e. "select x, y, (select max(foo) from table) AS foomax from table"
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added onupdate and ondelete keyword arguments to ForeignKey; propagate
+ to underlying ForeignKeyConstraint if present. (dont propagate in the
+ other direction, however)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fix to session.update() to preserve "dirty" status of incoming object
+
+ .. change::
+ :tags:
+ :tickets:
+
+ sending a selectable to an IN via the in_() function no longer creates
+ a "union" out of multiple selects; only one selectable to a the in_() function
+ is allowed now (make a union yourself if union is needed)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ improved support for disabling save-update cascade via cascade="none" etc.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "remote_side" argument to relation(), used only with self-referential
+ mappers to force the direction of the parent/child relationship. replaces
+ the usage of the "foreignkey" parameter for "switching" the direction.
+ "foreignkey" argument is deprecated for all uses and will eventually
+ be replaced by an argument dedicated to ForeignKey specification on mappers.
+
+.. changelog::
+ :version: 0.3.1
+ :released: Mon Nov 13 2006
+
+ .. change::
+ :tags: engine/pool
+ :tickets:
+
+ some new Pool utility classes, updated docs
+
+ .. change::
+ :tags: engine/pool
+ :tickets:
+
+ "use_threadlocal" on Pool defaults to False (same as create_engine)
+
+ .. change::
+ :tags: engine/pool
+ :tickets:
+
+ fixed direct execution of Compiled objects
+
+ .. change::
+ :tags: engine/pool
+ :tickets:
+
+ create_engine() reworked to be strict about incoming **kwargs. all keyword
+ arguments must be consumed by one of the dialect, connection pool, and engine
+ constructors, else a TypeError is thrown which describes the full set of
+ invalid kwargs in relation to the selected dialect/pool/engine configuration.
+
+ .. change::
+ :tags: databases/types
+ :tickets:
+
+ MySQL catches exception on "describe" and reports as NoSuchTableError
+
+ .. change::
+ :tags: databases/types
+ :tickets:
+
+ further fixes to sqlite booleans, weren't working as defaults
+
+ .. change::
+ :tags: databases/types
+ :tickets:
+
+ fix to postgres sequence quoting when using schemas
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the "delete" cascade will load in all child objects, if they were not
+ loaded already. this can be turned off (i.e. the old behavior) by setting
+ passive_deletes=True on a relation().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ adjustments to reworked eager query generation to not fail on circular
+ eager-loaded relationships (like backrefs)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed bug where eagerload() (nor lazyload()) option didn't properly
+ instruct the Query whether or not to use "nesting" when producing a
+ LIMIT query.
+
+ .. change::
+ :tags: orm
+ :tickets: 360
+
+ fixed bug in circular dependency sorting at flush time; if object A
+ contained a cyclical many-to-one relationship to object B, and object B
+ was just attached to object A, *but* object B itself wasnt changed,
+ the many-to-one synchronize of B's primary key attribute to A's foreign key
+ attribute wouldnt occur.
+
+ .. change::
+ :tags: orm
+ :tickets: 325
+
+ implemented from_obj argument for query.count, improves count function
+ on selectresults
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added an assertion within the "cascade" step of ORM relationships to check
+ that the class of object attached to a parent object is appropriate
+ (i.e. if A.items stores B objects, raise an error if a C is appended to A.items)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ new extension sqlalchemy.ext.associationproxy, provides transparent
+ "association object" mappings. new example
+ examples/association/proxied_association.py illustrates.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ improvement to single table inheritance to load full hierarchies beneath
+ the target class
+
+ .. change::
+ :tags: orm
+ :tickets: 362
+
+ fix to subtle condition in topological sort where a node could appear twice,
+ for
+
+ .. change::
+ :tags: orm
+ :tickets: 365
+
+ additional rework to topological sort, refactoring, for
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ "delete-orphan" for a certain type can be set on more than one parent class;
+ the instance is an "orphan" only if its not attached to *any* of those parents
+
+.. changelog::
+ :version: 0.3.0
+ :released: Sun Oct 22 2006
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ logging is now implemented via standard python "logging" module.
+ "echo" keyword parameters are still functional but set/unset
+ log levels for their respective classes/instances. all logging
+ can be controlled directly through the Python API by setting
+ INFO and DEBUG levels for loggers in the "sqlalchemy" namespace.
+ class-level logging is under "sqlalchemy.<module>.<classname>",
+ instance-level logging under "sqlalchemy.<module>.<classname>.0x..<00-FF>".
+ Test suite includes "--log-info" and "--log-debug" arguments
+ which work independently of --verbose/--quiet. Logging added
+ to orm to allow tracking of mapper configurations, row iteration.
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ the documentation-generation system has been overhauled to be
+ much simpler in design and more integrated with Markdown
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ sqlite boolean datatype converts False/True to 0/1 by default
+
+ .. change::
+ :tags: sqlite
+ :tickets: 335
+
+ fixes to Date/Time (SLDate/SLTime) types; works as good as postgres
+ now
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ fixes bug 261 (table reflection broken for MS-SQL case-sensitive
+ databases)
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ can now specify port for pymssql
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ introduces new "auto_identity_insert" option for auto-switching
+ between "SET IDENTITY_INSERT" mode when values specified for IDENTITY columns
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ now supports multi-column foreign keys
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ fix to reflecting date/datetime columns
+
+ .. change::
+ :tags: ms-sql
+ :tickets:
+
+ NCHAR and NVARCHAR type support added
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Oracle has experimental support for cx_Oracle.TIMESTAMP, which requires
+ a setinputsizes() call on the cursor that is now enabled via the
+ 'auto_setinputsizes' flag to the oracle dialect.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ aliases do not use "AS"
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ correctly raises NoSuchTableError when reflecting non-existent table
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ a fair amount of cleanup to the schema package, removal of ambiguous
+ methods, methods that are no longer needed. slightly more constrained
+ useage, greater emphasis on explicitness
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ the "primary_key" attribute of Table and other selectables becomes
+ a setlike ColumnCollection object; is ordered but not numerically
+ indexed. a comparison clause between two pks that are derived from the
+ same underlying tables (i.e. such as two Alias objects) can be generated
+ via table1.primary_key==table2.primary_key
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ ForeignKey(Constraint) supports "use_alter=True", to create/drop a foreign key
+ via ALTER. this allows circular foreign key relationships to be set up.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ append_item() methods removed from Table and Column; preferably
+ construct Table/Column/related objects inline, but if needed use
+ append_column(), append_foreign_key(), append_constraint(), etc.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ table.create() no longer returns the Table object, instead has no
+ return value. the usual case is that tables are created via metadata,
+ which is preferable since it will handle table dependencies.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ added UniqueConstraint (goes at Table level), CheckConstraint
+ (goes at Table or Column level).
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ index=False/unique=True on Column now creates a UniqueConstraint,
+ index=True/unique=False creates a plain Index,
+ index=True/unique=True on Column creates a unique Index. 'index'
+ and 'unique' keyword arguments to column are now boolean only; for
+ explcit names and groupings of indexes or unique constraints, use the
+ UniqueConstraint/Index constructs explicitly.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ added autoincrement=True to Column; will disable schema generation
+ of SERIAL/AUTO_INCREMENT/identity seq for postgres/mysql/mssql if
+ explicitly set to False
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ TypeEngine objects now have methods to deal with copying and comparing
+ values of their specific type. Currently used by the ORM, see below.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ fixed condition that occurred during reflection when a primary key
+ column was explciitly overridden, where the PrimaryKeyConstraint would
+ get both the reflected and the programmatic column doubled up
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ the "foreign_key" attribute on Column and ColumnElement in general
+ is deprecated, in favor of the "foreign_keys" list/set-based attribute,
+ which takes into account multiple foreign keys on one column.
+ "foreign_key" will return the first element in the "foreign_keys" list/set
+ or None if the list is empty.
+
+ .. change::
+ :tags: connections/pooling/execution
+ :tickets:
+
+ connection pool tracks open cursors and automatically closes them
+ if connection is returned to pool with cursors still opened. Can be
+ affected by options which cause it to raise an error instead, or to
+ do nothing. fixes issues with MySQL, others
+
+ .. change::
+ :tags: connections/pooling/execution
+ :tickets:
+
+ fixed bug where Connection wouldnt lose its Transaction
+ after commit/rollback
+
+ .. change::
+ :tags: connections/pooling/execution
+ :tickets:
+
+ added scalar() method to ComposedSQLEngine, ResultProxy
+
+ .. change::
+ :tags: connections/pooling/execution
+ :tickets:
+
+ ResultProxy will close() the underlying cursor when the ResultProxy
+ itself is closed. this will auto-close cursors for ResultProxy objects
+ that have had all their rows fetched (or had scalar() called).
+
+ .. change::
+ :tags: connections/pooling/execution
+ :tickets:
+
+ ResultProxy.fetchall() internally uses DBAPI fetchall() for better efficiency,
+ added to mapper iteration as well (courtesy Michael Twomey)
+
+ .. change::
+ :tags: construction, sql
+ :tickets: 292
+
+ changed "for_update" parameter to accept False/True/"nowait"
+ and "read", the latter two of which are interpreted only by
+ Oracle and Mysql
+
+ .. change::
+ :tags: construction, sql
+ :tickets:
+
+ added extract() function to sql dialect
+ (SELECT extract(field FROM expr))
+
+ .. change::
+ :tags: construction, sql
+ :tickets:
+
+ BooleanExpression includes new "negate" argument to specify
+ the appropriate negation operator if one is available.
+
+ .. change::
+ :tags: construction, sql
+ :tickets:
+
+ calling a negation on an "IN" or "IS" clause will result in
+ "NOT IN", "IS NOT" (as opposed to NOT (x IN y)).
+
+ .. change::
+ :tags: construction, sql
+ :tickets: 172
+
+ Function objects know what to do in a FROM clause now. their
+ behavior should be the same, except now you can also do things like
+ select(['*'], from_obj=[func.my_function()]) to get multiple
+ columns from the result, or even use sql.column() constructs to name the
+ return columns
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ attribute tracking modified to be more intelligent about detecting
+ changes, particularly with mutable types. TypeEngine objects now
+ take a greater role in defining how to compare two scalar instances,
+ including the addition of a MutableType mixin which is implemented by
+ PickleType. unit-of-work now tracks the "dirty" list as an expression
+ of all persistent objects where the attribute manager detects changes.
+ The basic issue thats fixed is detecting changes on PickleType
+ objects, but also generalizes type handling and "modified" object
+ checking to be more complete and extensible.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ a wide refactoring to "attribute loader" and "options" architectures.
+ ColumnProperty and PropertyLoader define their loading behaivor via switchable
+ "strategies", and MapperOptions no longer use mapper/property copying
+ in order to function; they are instead propagated via QueryContext
+ and SelectionContext objects at query/instances time.
+ All of the internal copying of mappers and properties that was used to handle
+ inheritance as well as options() has been removed; the structure
+ of mappers and properties is much simpler than before and is clearly laid out
+ in the new 'interfaces' module.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ related to the mapper/property overhaul, internal refactoring to
+ mapper instances() method to use a SelectionContext object to track
+ state during the operation.
+ SLIGHT API BREAKAGE: the append_result() and populate_instances()
+ methods on MapperExtension have a slightly different method signature
+ now as a result of the change; hoping that these methods are not
+ in widespread use as of yet.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ instances() method moved to Query now, backwards-compatible
+ version remains on Mapper.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added contains_eager() MapperOption, used in conjunction with
+ instances() to specify properties that should be eagerly loaded
+ from the result set, using their plain column names by default, or translated
+ given an custom row-translation function.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ more rearrangements of unit-of-work commit scheme to better allow
+ dependencies within circular flushes to work properly...updated
+ task traversal/logging implementation
+
+ .. change::
+ :tags: orm
+ :tickets: 321
+
+ polymorphic mappers (i.e. using inheritance) now produces INSERT
+ statements in order of tables across all inherited classes
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added an automatic "row switch" feature to mapping, which will
+ detect a pending instance/deleted instance pair with the same
+ identity key and convert the INSERT/DELETE to a single UPDATE
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ "association" mappings simplified to take advantage of
+ automatic "row switch" feature
+
+ .. change::
+ :tags: orm
+ :tickets: 212
+
+ "custom list classes" is now implemented via the "collection_class"
+ keyword argument to relation(). the old way still works but is
+ deprecated
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added "viewonly" flag to relation(), allows construction of
+ relations that have no effect on the flush() process.
+
+ .. change::
+ :tags: orm
+ :tickets: 292
+
+ added "lockmode" argument to base Query select/get functions,
+ including "with_lockmode" function to get a Query copy that has
+ a default locking mode. Will translate "read"/"update"
+ arguments into a for_update argument on the select side.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ implemented "version check" logic in Query/Mapper, used
+ when version_id_col is in effect and query.with_lockmode()
+ is used to get() an instance thats already loaded
+
+ .. change::
+ :tags: orm
+ :tickets: 208
+
+ post_update behavior improved; does a better job at not
+ updating too many rows, updates only required columns
+
+ .. change::
+ :tags: orm
+ :tickets: 308
+
+ adjustments to eager loading so that its "eager chain" is
+ kept separate from the normal mapper setup, thereby
+ preventing conflicts with lazy loader operation, fixes
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fix to deferred group loading
+
+ .. change::
+ :tags: orm
+ :tickets: 346
+
+ session.flush() wont close a connection it opened
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added "batch=True" flag to mapper; if False, save_obj
+ will fully save one object at a time including calls
+ to before_XXXX and after_XXXX
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added "column_prefix=None" argument to mapper; prepends the
+ given string (typically '_') to column-based attributes automatically
+ set up from the mapper's Table
+
+ .. change::
+ :tags: orm
+ :tickets: 315
+
+ specifying joins in the from_obj argument of query.select() will
+ replace the main table of the query, if the table is somewhere within
+ the given from_obj. this makes it possible to produce custom joins and
+ outerjoins in queries without the main table getting added twice.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ eagerloading is adjusted to more thoughtfully attach its LEFT OUTER JOINs
+ to the given query, looking for custom "FROM" clauses that may have
+ already been set up.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added join_to and outerjoin_to transformative methods to SelectResults,
+ to build up join/outerjoin conditions based on property names. also
+ added select_from to explicitly set from_obj parameter.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ removed "is_primary" flag from mapper.
--- /dev/null
+
+==============
+0.4 Changelog
+==============
+
+
+.. changelog::
+ :version: 0.4.8
+ :released: Sun Oct 12 2008
+
+ .. change::
+ :tags: orm
+ :tickets: 1039
+
+ Fixed bug regarding inherit_condition passed
+ with "A=B" versus "B=A" leading to errors
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Changes made to new, dirty and deleted
+ collections in
+ SessionExtension.before_flush() will take
+ effect for that flush.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added label() method to InstrumentedAttribute
+ to establish forwards compatibility with 0.5.
+
+ .. change::
+ :tags: sql
+ :tickets: 1074
+
+ column.in_(someselect) can now be used as
+ a columns-clause expression without the subquery
+ bleeding into the FROM clause
+
+ .. change::
+ :tags: mysql
+ :tickets: 1146
+
+ Added MSMediumInteger type.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 968
+
+ Supplied a custom strftime() function which
+ handles dates before 1900.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ String's (and Unicode's, UnicodeText's, etc.)
+ convert_unicode logic disabled in the sqlite dialect,
+ to adjust for pysqlite 2.5.0's new requirement that
+ only Python unicode objects are accepted;
+ http://itsystementwicklung.de/pipermail/list-pysqlite/2008-March/000018.html
+
+ .. change::
+ :tags: oracle
+ :tickets: 1155
+
+ has_sequence() now takes schema name into account
+
+ .. change::
+ :tags: oracle
+ :tickets: 1121
+
+ added BFILE to the list of reflected types
+
+.. changelog::
+ :version: 0.4.7p1
+ :released: Thu Jul 31 2008
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added "add()" and "add_all()" to scoped_session
+ methods. Workaround for 0.4.7:
+
+ from sqlalchemy.orm.scoping import ScopedSession,\
+ instrument
+ setattr(
+ ScopedSession, "add", instrument("add"))
+ setattr(
+ ScopedSession, "add_all", instrument("add_all"))
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed non-2.3 compatible usage of set() and generator
+ expression within relation().
+
+.. changelog::
+ :version: 0.4.7
+ :released: Sat Jul 26 2008
+
+ .. change::
+ :tags: orm
+ :tickets: 1058
+
+ The contains() operator when used with many-to-many
+ will alias() the secondary (association) table so
+ that multiple contains() calls will not conflict
+ with each other
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed bug preventing merge() from functioning in
+ conjunction with a comparable_property()
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the enable_typechecks=False setting on relation()
+ now only allows subtypes with inheriting mappers.
+ Totally unrelated types, or subtypes not set up with
+ mapper inheritance against the target mapper are
+ still not allowed.
+
+ .. change::
+ :tags: orm
+ :tickets: 976
+
+ Added is_active flag to Sessions to detect when
+ a transaction is in progress. This
+ flag is always True with a "transactional"
+ (in 0.5 a non-"autocommit") Session.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed bug when calling select([literal('foo')])
+ or select([bindparam('foo')]).
+
+ .. change::
+ :tags: schema
+ :tickets: 571
+
+ create_all(), drop_all(), create(), drop() all raise
+ an error if the table name or schema name contains
+ more characters than that dialect's configured
+ character limit. Some DB's can handle too-long
+ table names during usage, and SQLA can handle this
+ as well. But various reflection/
+ checkfirst-during-create scenarios fail since we are
+ looking for the name within the DB's catalog tables.
+
+ .. change::
+ :tags: schema
+ :tickets: 571, 820
+
+ The index name generated when you say "index=True"
+ on a Column is truncated to the length appropriate
+ for the dialect. Additionally, an Index with a too-
+ long name cannot be explicitly dropped with
+ Index.drop(), similar to.
+
+ .. change::
+ :tags: postgres
+ :tickets:
+
+ Repaired server_side_cursors to properly detect
+ text() clauses.
+
+ .. change::
+ :tags: postgres
+ :tickets: 1092
+
+ Added PGCidr type.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Added 'CALL' to the list of SQL keywords which return
+ result rows.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Oracle get_default_schema_name() "normalizes" the name
+ before returning, meaning it returns a lower-case name
+ when the identifier is detected as case insensitive.
+
+ .. change::
+ :tags: oracle
+ :tickets: 709
+
+ creating/dropping tables takes schema name into account
+ when searching for the existing table, so that tables
+ in other owner namespaces with the same name do not
+ conflict
+
+ .. change::
+ :tags: oracle
+ :tickets: 1062
+
+ Cursors now have "arraysize" set to 50 by default on
+ them, the value of which is configurable using the
+ "arraysize" argument to create_engine() with the
+ Oracle dialect. This to account for cx_oracle's default
+ setting of "1", which has the effect of many round trips
+ being sent to Oracle. This actually works well in
+ conjunction with BLOB/CLOB-bound cursors, of which
+ there are any number available but only for the life of
+ that row request (so BufferedColumnRow is still needed,
+ but less so).
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ sqlite
+ - add SLFloat type, which matches the SQLite REAL
+ type affinity. Previously, only SLNumeric was provided
+ which fulfills NUMERIC affinity, but that's not the
+ same as REAL.
+
+.. changelog::
+ :version: 0.4.6
+ :released: Sat May 10 2008
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fix to the recent relation() refactoring which fixes
+ exotic viewonly relations which join between local and
+ remote table multiple times, with a common column shared
+ between the joins.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Also re-established viewonly relation() configurations
+ that join across multiple tables.
+
+ .. change::
+ :tags: orm
+ :tickets: 610
+
+ Added experimental relation() flag to help with
+ primaryjoins across functions, etc.,
+ _local_remote_pairs=[tuples]. This complements a complex
+ primaryjoin condition allowing you to provide the
+ individual column pairs which comprise the relation's
+ local and remote sides. Also improved lazy load SQL
+ generation to handle placing bind params inside of
+ functions and other expressions. (partial progress
+ towards)
+
+ .. change::
+ :tags: orm
+ :tickets: 1036
+
+ repaired single table inheritance such that you
+ can single-table inherit from a joined-table inherting
+ mapper without issue.
+
+ .. change::
+ :tags: orm
+ :tickets: 1027
+
+ Fixed "concatenate tuple" bug which could occur with
+ Query.order_by() if clause adaption had taken place.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Removed ancient assertion that mapped selectables require
+ "alias names" - the mapper creates its own alias now if
+ none is present. Though in this case you need to use the
+ class, not the mapped selectable, as the source of column
+ attributes - so a warning is still issued.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixes to the "exists" function involving inheritance (any(),
+ has(), ~contains()); the full target join will be rendered
+ into the EXISTS clause for relations that link to subclasses.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ restored usage of append_result() extension method for primary
+ query rows, when the extension is present and only a single-
+ entity result is being returned.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Also re-established viewonly relation() configurations that
+ join across multiple tables.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ removed ancient assertion that mapped selectables require
+ "alias names" - the mapper creates its own alias now if
+ none is present. Though in this case you need to use
+ the class, not the mapped selectable, as the source of
+ column attributes - so a warning is still issued.
+
+ .. change::
+ :tags: orm
+ :tickets: 1015
+
+ refined mapper._save_obj() which was unnecessarily calling
+ __ne__() on scalar values during flush
+
+ .. change::
+ :tags: orm
+ :tickets: 1019
+
+ added a feature to eager loading whereby subqueries set
+ as column_property() with explicit label names (which is not
+ necessary, btw) will have the label anonymized when
+ the instance is part of the eager join, to prevent
+ conflicts with a subquery or column of the same name
+ on the parent object.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ set-based collections |=, -=, ^= and &= are stricter about
+ their operands and only operate on sets, frozensets or
+ subclasses of the collection type. Previously, they would
+ accept any duck-typed set.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added an example dynamic_dict/dynamic_dict.py, illustrating
+ a simple way to place dictionary behavior on top of
+ a dynamic_loader.
+
+ .. change::
+ :tags: declarative, extension
+ :tickets:
+
+ Joined table inheritance mappers use a slightly relaxed
+ function to create the "inherit condition" to the parent
+ table, so that other foreign keys to not-yet-declared
+ Table objects don't trigger an error.
+
+ .. change::
+ :tags: declarative, extension
+ :tickets:
+
+ fixed reentrant mapper compile hang when
+ a declared attribute is used within ForeignKey,
+ ie. ForeignKey(MyOtherClass.someattribute)
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added COLLATE support via the .collate(<collation>)
+ expression operator and collate(<expr>, <collation>) sql
+ function.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed bug with union() when applied to non-Table connected
+ select statements
+
+ .. change::
+ :tags: sql
+ :tickets: 1014
+
+ improved behavior of text() expressions when used as
+ FROM clauses, such as select().select_from(text("sometext"))
+
+ .. change::
+ :tags: sql
+ :tickets: 1021
+
+ Column.copy() respects the value of "autoincrement",
+ fixes usage with Migrate
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Pool listeners can now be provided as a dictionary of
+ callables or a (possibly partial) duck-type of
+ PoolListener, your choice.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ added "rollback_returned" option to Pool which will
+ disable the rollback() issued when connections are
+ returned. This flag is only safe to use with a database
+ which does not support transactions (i.e. MySQL/MyISAM).
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ set-based association proxies |=, -=, ^= and &= are
+ stricter about their operands and only operate on sets,
+ frozensets or other association proxies. Previously, they
+ would accept any duck-typed set.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1005
+
+ Added "odbc_autotranslate" parameter to engine / dburi
+ parameters. Any given string will be passed through to the
+ ODBC connection string as:
+
+ "AutoTranslate=%s" % odbc_autotranslate
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Added "odbc_options" parameter to engine / dburi
+ parameters. The given string is simply appended to the
+ SQLAlchemy-generated odbc connection string.
+
+ This should obviate the need of adding a myriad of ODBC
+ options in the future.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ Handle the "SUBSTRING(:string FROM :start FOR :length)"
+ builtin.
+
+.. changelog::
+ :version: 0.4.5
+ :released: Fri Apr 04 2008
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ A small change in behavior to session.merge() - existing
+ objects are checked for based on primary key attributes, not
+ necessarily _instance_key. So the widely requested
+ capability, that:
+
+ x = MyObject(id=1)
+ x = sess.merge(x)
+
+ will in fact load MyObject with id #1 from the database if
+ present, is now available. merge() still copies the state
+ of the given object to the persistent one, so an example
+ like the above would typically have copied "None" from all
+ attributes of "x" onto the persistent copy. These can be
+ reverted using session.expire(x).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Also fixed behavior in merge() whereby collection elements
+ present on the destination but not the merged collection
+ were not being removed from the destination.
+
+ .. change::
+ :tags: orm
+ :tickets: 995
+
+ Added a more aggressive check for "uncompiled mappers",
+ helps particularly with declarative layer
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The methodology behind "primaryjoin"/"secondaryjoin" has
+ been refactored. Behavior should be slightly more
+ intelligent, primarily in terms of error messages which
+ have been pared down to be more readable. In a slight
+ number of scenarios it can better resolve the correct
+ foreign key than before.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added comparable_property(), adds query Comparator
+ behavior to regular, unmanaged Python properties
+
+ .. change::
+ :tags: orm, Company.employees.of_type(Engineer), 'machines'
+ :tickets:
+
+ the functionality of query.with_polymorphic() has
+ been added to mapper() as a configuration option.
+
+ It's set via several forms:
+ with_polymorphic='*'
+ with_polymorphic=[mappers]
+ with_polymorphic=('*', selectable)
+ with_polymorphic=([mappers], selectable)
+
+ This controls the default polymorphic loading strategy
+ for inherited mappers. When a selectable is not given,
+ outer joins are created for all joined-table inheriting
+ mappers requested. Note that the auto-create of joins
+ is not compatible with concrete table inheritance.
+
+ The existing select_table flag on mapper() is now
+ deprecated and is synonymous with
+ with_polymorphic('*', select_table). Note that the
+ underlying "guts" of select_table have been
+ completely removed and replaced with the newer,
+ more flexible approach.
+
+ The new approach also automatically allows eager loads
+ to work for subclasses, if they are present, for
+ example
+ sess.query(Company).options(
+ eagerload_all(
+
+ ))
+ to load Company objects, their employees, and the
+ 'machines' collection of employees who happen to be
+ Engineers. A "with_polymorphic" Query option should be
+ introduced soon as well which would allow per-Query
+ control of with_polymorphic() on relations.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added two "experimental" features to Query,
+ "experimental" in that their specific name/behavior
+ is not carved in stone just yet: _values() and
+ _from_self(). We'd like feedback on these.
+
+ - _values(*columns) is given a list of column
+ expressions, and returns a new Query that only
+ returns those columns. When evaluated, the return
+ value is a list of tuples just like when using
+ add_column() or add_entity(), the only difference is
+ that "entity zero", i.e. the mapped class, is not
+ included in the results. This means it finally makes
+ sense to use group_by() and having() on Query, which
+ have been sitting around uselessly until now.
+
+ A future change to this method may include that its
+ ability to join, filter and allow other options not
+ related to a "resultset" are removed, so the feedback
+ we're looking for is how people want to use
+ _values()...i.e. at the very end, or do people prefer
+ to continue generating after it's called.
+
+ - _from_self() compiles the SELECT statement for the
+ Query (minus any eager loaders), and returns a new
+ Query that selects from that SELECT. So basically you
+ can query from a Query without needing to extract the
+ SELECT statement manually. This gives meaning to
+ operations like query[3:5]._from_self().filter(some
+ criterion). There's not much controversial here
+ except that you can quickly create highly nested
+ queries that are less efficient, and we want feedback
+ on the naming choice.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.order_by() and query.group_by() will accept
+ multiple arguments using *args (like select()
+ already does).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added some convenience descriptors to Query:
+ query.statement returns the full SELECT construct,
+ query.whereclause returns just the WHERE part of the
+ SELECT construct.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed/covered case when using a False/0 value as a
+ polymorphic discriminator.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug which was preventing synonym() attributes from
+ being used with inheritance
+
+ .. change::
+ :tags: orm
+ :tickets: 996
+
+ Fixed SQL function truncation of trailing underscores
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ When attributes are expired on a pending instance, an
+ error will not be raised when the "refresh" action is
+ triggered and no result is found.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session.execute can now find binds from metadata
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Adjusted the definition of "self-referential" to be any
+ two mappers with a common parent (this affects whether or
+ not aliased=True is required when joining with Query).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Made some fixes to the "from_joinpoint" argument to
+ query.join() so that if the previous join was aliased and
+ this one isn't, the join still happens successfully.
+
+ .. change::
+ :tags: orm
+ :tickets: 895
+
+ Assorted "cascade deletes" fixes:
+ - Fixed "cascade delete" operation of dynamic relations,
+ which had only been implemented for foreign-key
+ nulling behavior in 0.4.2 and not actual cascading
+ deletes
+
+ - Delete cascade without delete-orphan cascade on a
+ many-to-one will not delete orphans which were
+ disconnected from the parent before session.delete()
+ is called on the parent (one-to-many already had
+ this).
+
+ - Delete cascade with delete-orphan will delete orphans
+ whether or not it remains attached to its also-deleted
+ parent.
+
+ - delete-orphan casacde is properly detected on relations
+ that are present on superclasses when using inheritance.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed order_by calculation in Query to properly alias
+ mapper-config'ed order_by when using select_from()
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Refactored the diffing logic that kicks in when replacing
+ one collection with another into collections.bulk_replace,
+ useful to anyone building multi-level collections.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Cascade traversal algorithm converted from recursive to
+ iterative to support deep object graphs.
+
+ .. change::
+ :tags: sql
+ :tickets: 999
+
+ schema-qualified tables now will place the schemaname
+ ahead of the tablename in all column expressions as well
+ as when generating column labels. This prevents cross-
+ schema name collisions in all cases
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ can now allow selects which correlate all FROM clauses
+ and have no FROM themselves. These are typically
+ used in a scalar context, i.e. SELECT x, (SELECT x WHERE y)
+ FROM table. Requires explicit correlate() call.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ 'name' is no longer a required constructor argument for
+ Column(). It (and .key) may now be deferred until the
+ column is added to a Table.
+
+ .. change::
+ :tags: sql
+ :tickets: 791, 993
+
+ like(), ilike(), contains(), startswith(), endswith() take
+ an optional keyword argument "escape=<somestring>", which
+ is set as the escape character using the syntax "x LIKE y
+ ESCAPE '<somestring>'".
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ random() is now a generic sql function and will compile to
+ the database's random implementation, if any.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ update().values() and insert().values() take keyword
+ arguments.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed an issue in select() regarding its generation of
+ FROM clauses, in rare circumstances two clauses could be
+ produced when one was intended to cancel out the other.
+ Some ORM queries with lots of eager loads might have seen
+ this symptom.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The case() function now also takes a dictionary as its
+ whens parameter. It also interprets the "THEN"
+ expressions as values by default, meaning case([(x==y,
+ "foo")]) will interpret "foo" as a bound value, not a SQL
+ expression. use text(expr) for literal SQL expressions in
+ this case. For the criterion itself, these may be literal
+ strings only if the "value" keyword is present, otherwise
+ SA will force explicit usage of either text() or
+ literal().
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ The "owner" keyword on Table is now deprecated, and is
+ exactly synonymous with the "schema" keyword. Tables can
+ now be reflected with alternate "owner" attributes,
+ explicitly stated on the Table object or not using
+ "schema".
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ All of the "magic" searching for synonyms, DBLINKs etc.
+ during table reflection are disabled by default unless you
+ specify "oracle_resolve_synonyms=True" on the Table
+ object. Resolving synonyms necessarily leads to some
+ messy guessing which we'd rather leave off by default.
+ When the flag is set, tables and related tables will be
+ resolved against synonyms in all cases, meaning if a
+ synonym exists for a particular table, reflection will use
+ it when reflecting related tables. This is stickier
+ behavior than before which is why it's off by default.
+
+ .. change::
+ :tags: declarative, extension
+ :tickets:
+
+ The "synonym" function is now directly usable with
+ "declarative". Pass in the decorated property using the
+ "descriptor" keyword argument, e.g.: somekey =
+ synonym('_somekey', descriptor=property(g, s))
+
+ .. change::
+ :tags: declarative, extension
+ :tickets:
+
+ The "deferred" function is usable with "declarative".
+ Simplest usage is to declare deferred and Column together,
+ e.g.: data = deferred(Column(Text))
+
+ .. change::
+ :tags: declarative, extension
+ :tickets:
+
+ Declarative also gained @synonym_for(...) and
+ @comparable_using(...), front-ends for synonym and
+ comparable_property.
+
+ .. change::
+ :tags: declarative, extension
+ :tickets: 995
+
+ Improvements to mapper compilation when using declarative;
+ already-compiled mappers will still trigger compiles of
+ other uncompiled mappers when used
+
+ .. change::
+ :tags: declarative, extension
+ :tickets:
+
+ Declarative will complete setup for Columns lacking names,
+ allows a more DRY syntax.
+
+ class Foo(Base):
+ __tablename__ = 'foos'
+ id = Column(Integer, primary_key=True)
+
+ .. change::
+ :tags: declarative, extension
+ :tickets:
+
+ inheritance in declarative can be disabled when sending
+ "inherits=None" to __mapper_args__.
+
+ .. change::
+ :tags: declarative, extension
+ :tickets:
+
+ declarative_base() takes optional kwarg "mapper", which
+ is any callable/class/method that produces a mapper,
+ such as declarative_base(mapper=scopedsession.mapper).
+ This property can also be set on individual declarative
+ classes using the "__mapper_cls__" property.
+
+ .. change::
+ :tags: postgres
+ :tickets: 1001
+
+ Got PG server side cursors back into shape, added fixed
+ unit tests as part of the default test suite. Added
+ better uniqueness to the cursor ID
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ The "owner" keyword on Table is now deprecated, and is
+ exactly synonymous with the "schema" keyword. Tables can
+ now be reflected with alternate "owner" attributes,
+ explicitly stated on the Table object or not using
+ "schema".
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ All of the "magic" searching for synonyms, DBLINKs etc.
+ during table reflection are disabled by default unless you
+ specify "oracle_resolve_synonyms=True" on the Table
+ object. Resolving synonyms necessarily leads to some
+ messy guessing which we'd rather leave off by default.
+ When the flag is set, tables and related tables will be
+ resolved against synonyms in all cases, meaning if a
+ synonym exists for a particular table, reflection will use
+ it when reflecting related tables. This is stickier
+ behavior than before which is why it's off by default.
+
+ .. change::
+ :tags: mssql
+ :tickets: 979
+
+ Reflected tables will now automatically load other tables
+ which are referenced by Foreign keys in the auto-loaded
+ table,.
+
+ .. change::
+ :tags: mssql
+ :tickets: 916
+
+ Added executemany check to skip identity fetch,.
+
+ .. change::
+ :tags: mssql
+ :tickets: 884
+
+ Added stubs for small date type.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Added a new 'driver' keyword parameter for the pyodbc dialect.
+ Will substitute into the ODBC connection string if given,
+ defaults to 'SQL Server'.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Added a new 'max_identifier_length' keyword parameter for
+ the pyodbc dialect.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Improvements to pyodbc + Unix. If you couldn't get that
+ combination to work before, please try again.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ The connection.info keys the dialect uses to cache server
+ settings have changed and are now namespaced.
+
+.. changelog::
+ :version: 0.4.4
+ :released: Wed Mar 12 2008
+
+ .. change::
+ :tags: sql
+ :tickets: 975
+
+ Can again create aliases of selects against textual FROM
+ clauses.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The value of a bindparam() can be a callable, in which
+ case it's evaluated at statement execution time to get the
+ value.
+
+ .. change::
+ :tags: sql
+ :tickets: 978
+
+ Added exception wrapping/reconnect support to result set
+ fetching. Reconnect works for those databases that raise
+ a catchable data error during results (i.e. doesn't work
+ on MySQL)
+
+ .. change::
+ :tags: sql
+ :tickets: 936
+
+ Implemented two-phase API for "threadlocal" engine, via
+ engine.begin_twophase(), engine.prepare()
+
+ .. change::
+ :tags: sql
+ :tickets: 986
+
+ Fixed bug which was preventing UNIONS from being
+ cloneable.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added "bind" keyword argument to insert(), update(),
+ delete() and DDL(). The .bind property is now assignable
+ on those statements as well as on select().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Insert statements can now be compiled with extra "prefix"
+ words between INSERT and INTO, for vendor extensions like
+ MySQL's INSERT IGNORE INTO table.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ any(), has(), contains(), ~contains(), attribute level ==
+ and != now work properly with self-referential relations -
+ the clause inside the EXISTS is aliased on the "remote"
+ side to distinguish it from the parent table. This
+ applies to single table self-referential as well as
+ inheritance-based self-referential.
+
+ .. change::
+ :tags: orm
+ :tickets: 985
+
+ Repaired behavior of == and != operators at the relation()
+ level when compared against NULL for one-to-one relations
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug whereby session.expire() attributes were not
+ loading on an polymorphically-mapped instance mapped by a
+ select_table mapper.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added query.with_polymorphic() - specifies a list of
+ classes which descend from the base class, which will be
+ added to the FROM clause of the query. Allows subclasses
+ to be used within filter() criterion as well as eagerly
+ loads the attributes of those subclasses.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Your cries have been heard: removing a pending item from
+ an attribute or collection with delete-orphan expunges the
+ item from the session; no FlushError is raised. Note that
+ if you session.save()'ed the pending item explicitly, the
+ attribute/collection removal still knocks it out.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ session.refresh() and session.expire() raise an error when
+ called on instances which are not persistent within the
+ session
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed potential generative bug when the same Query was
+ used to generate multiple Query objects using join().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug which was introduced in 0.4.3, whereby loading
+ an already-persistent instance mapped with joined table
+ inheritance would trigger a useless "secondary" load from
+ its joined table, when using the default "select"
+ polymorphic_fetch. This was due to attributes being
+ marked as expired during its first load and not getting
+ unmarked from the previous "secondary" load. Attributes
+ are now unexpired based on presence in __dict__ after any
+ load or commit operation succeeds.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Deprecated Query methods apply_sum(), apply_max(),
+ apply_min(), apply_avg(). Better methodologies are
+ coming....
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ relation() can accept a callable for its first argument,
+ which returns the class to be related. This is in place
+ to assist declarative packages to define relations without
+ classes yet being in place.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added a new "higher level" operator called "of_type()":
+ used in join() as well as with any() and has(), qualifies
+ the subclass which will be used in filter criterion, e.g.:
+
+ query.filter(Company.employees.of_type(Engineer).
+ any(Engineer.name=='foo'))
+
+ or
+
+ query.join(Company.employees.of_type(Engineer)).
+ filter(Engineer.name=='foo')
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Preventive code against a potential lost-reference bug in
+ flush().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Expressions used in filter(), filter_by() and others, when
+ they make usage of a clause generated from a relation
+ using the identity of a child object (e.g.,
+ filter(Parent.child==<somechild>)), evaluate the actual
+ primary key value of <somechild> at execution time so that
+ the autoflush step of the Query can complete, thereby
+ populating the PK value of <somechild> in the case that
+ <somechild> was pending.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ setting the relation()-level order by to a column in the
+ many-to-many "secondary" table will now work with eager
+ loading, previously the "order by" wasn't aliased against
+ the secondary table's alias.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Synonyms riding on top of existing descriptors are now
+ full proxies to those descriptors.
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Invalid SQLite connection URLs now raise an error.
+
+ .. change::
+ :tags: dialects
+ :tickets: 981
+
+ postgres TIMESTAMP renders correctly
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ postgres PGArray is a "mutable" type by default; when used
+ with the ORM, mutable-style equality/ copy-on-write
+ techniques are used to test for changes.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ a new super-small "declarative" extension has been added,
+ which allows Table and mapper() configuration to take
+ place inline underneath a class declaration. This
+ extension differs from ActiveMapper and Elixir in that it
+ does not redefine any SQLAlchemy semantics at all; literal
+ Column, Table and relation() constructs are used to define
+ the class behavior and table definition.
+
+.. changelog::
+ :version: 0.4.3
+ :released: Thu Feb 14 2008
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added "schema.DDL", an executable free-form DDL statement.
+ DDLs can be executed in isolation or attached to Table or
+ MetaData instances and executed automatically when those
+ objects are created and/or dropped.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Table columns and constraints can be overridden on a an
+ existing table (such as a table that was already reflected)
+ using the 'useexisting=True' flag, which now takes into
+ account the arguments passed along with it.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added a callable-based DDL events interface, adds hooks
+ before and after Tables and MetaData create and drop.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added generative where(<criterion>) method to delete() and
+ update() constructs which return a new object with criterion
+ joined to existing criterion via AND, just like
+ select().where().
+
+ .. change::
+ :tags: sql
+ :tickets: 727
+
+ Added "ilike()" operator to column operations. Compiles to
+ ILIKE on postgres, lower(x) LIKE lower(y) on all
+ others.
+
+ .. change::
+ :tags: sql
+ :tickets: 943
+
+ Added "now()" as a generic function; on SQLite, Oracle
+ and MSSQL compiles as "CURRENT_TIMESTAMP"; "now()" on
+ all others.
+
+ .. change::
+ :tags: sql
+ :tickets: 962
+
+ The startswith(), endswith(), and contains() operators now
+ concatenate the wildcard operator with the given operand in
+ SQL, i.e. "'%' || <bindparam>" in all cases, accept
+ text('something') operands properly
+
+ .. change::
+ :tags: sql
+ :tickets: 962
+
+ cast() accepts text('something') and other non-literal
+ operands properly
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fixed bug in result proxy where anonymously generated
+ column labels would not be accessible using their straight
+ string name
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Deferrable constraints can now be defined.
+
+ .. change::
+ :tags: sql
+ :tickets: 915
+
+ Added "autocommit=True" keyword argument to select() and
+ text(), as well as generative autocommit() method on
+ select(); for statements which modify the database through
+ some user-defined means other than the usual INSERT/UPDATE/
+ DELETE etc. This flag will enable "autocommit" behavior
+ during execution if no transaction is in progress.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The '.c.' attribute on a selectable now gets an entry for
+ every column expression in its columns clause. Previously,
+ "unnamed" columns like functions and CASE statements weren't
+ getting put there. Now they will, using their full string
+ representation if no 'name' is available.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ a CompositeSelect, i.e. any union(), union_all(),
+ intersect(), etc. now asserts that each selectable contains
+ the same number of columns. This conforms to the
+ corresponding SQL requirement.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The anonymous 'label' generated for otherwise unlabeled
+ functions and expressions now propagates outwards at compile
+ time for expressions like select([select([func.foo()])]).
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Building on the above ideas, CompositeSelects now build up
+ their ".c." collection based on the names present in the
+ first selectable only; corresponding_column() now works
+ fully for all embedded selectables.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Oracle and others properly encode SQL used for defaults like
+ sequences, etc., even if no unicode idents are used since
+ identifier preparer may return a cached unicode identifier.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Column and clause comparisons to datetime objects on the
+ left hand side of the expression now work (d < table.c.col).
+ (datetimes on the RHS have always worked, the LHS exception
+ is a quirk of the datetime implementation.)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Every Session.begin() must now be accompanied by a
+ corresponding commit() or rollback() unless the session is
+ closed with Session.close(). This also includes the begin()
+ which is implicit to a session created with
+ transactional=True. The biggest change introduced here is
+ that when a Session created with transactional=True raises
+ an exception during flush(), you must call
+ Session.rollback() or Session.close() in order for that
+ Session to continue after an exception.
+
+ .. change::
+ :tags: orm
+ :tickets: 961
+
+ Fixed merge() collection-doubling bug when merging transient
+ entities with backref'ed collections.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ merge(dont_load=True) does not accept transient entities,
+ this is in continuation with the fact that
+ merge(dont_load=True) does not accept any "dirty" objects
+ either.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added standalone "query" class attribute generated by a
+ scoped_session. This provides MyClass.query without using
+ Session.mapper. Use via:
+
+ MyClass.query = Session.query_property()
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The proper error message is raised when trying to access
+ expired instance attributes with no session present
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ dynamic_loader() / lazy="dynamic" now accepts and uses
+ the order_by parameter in the same way in which it works
+ with relation().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added expire_all() method to Session. Calls expire() for
+ all persistent instances. This is handy in conjunction
+ with...
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Instances which have been partially or fully expired will
+ have their expired attributes populated during a regular
+ Query operation which affects those objects, preventing a
+ needless second SQL statement for each instance.
+
+ .. change::
+ :tags: orm
+ :tickets: 938
+
+ Dynamic relations, when referenced, create a strong
+ reference to the parent object so that the query still has a
+ parent to call against even if the parent is only created
+ (and otherwise dereferenced) within the scope of a single
+ expression.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added a mapper() flag "eager_defaults". When set to True,
+ defaults that are generated during an INSERT or UPDATE
+ operation are post-fetched immediately, instead of being
+ deferred until later. This mimics the old 0.3 behavior.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.join() can now accept class-mapped attributes as
+ arguments. These can be used in place or in any combination
+ with strings. In particular this allows construction of
+ joins to subclasses on a polymorphic relation, i.e.:
+
+ query(Company).join(['employees', Engineer.name])
+
+ .. change::
+ :tags: orm, ('employees', people.join(engineer)), Engineer.name
+ :tickets:
+
+ query.join() can also accept tuples of attribute name/some
+ selectable as arguments. This allows construction of joins
+ *from* subclasses of a polymorphic relation, i.e.:
+
+ query(Company).\
+ join(
+
+ )
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ General improvements to the behavior of join() in
+ conjunction with polymorphic mappers, i.e. joining from/to
+ polymorphic mappers and properly applying aliases.
+
+ .. change::
+ :tags: orm
+ :tickets: 933
+
+ Fixed/improved behavior when a mapper determines the natural
+ "primary key" of a mapped join, it will more effectively
+ reduce columns which are equivalent via foreign key
+ relation. This affects how many arguments need to be sent
+ to query.get(), among other things.
+
+ .. change::
+ :tags: orm
+ :tickets: 946
+
+ The lazy loader can now handle a join condition where the
+ "bound" column (i.e. the one that gets the parent id sent as
+ a bind parameter) appears more than once in the join
+ condition. Specifically this allows the common task of a
+ relation() which contains a parent-correlated subquery, such
+ as "select only the most recent child item".
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug in polymorphic inheritance where an incorrect
+ exception is raised when base polymorphic_on column does not
+ correspond to any columns within the local selectable of an
+ inheriting mapper more than one level deep
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug in polymorphic inheritance which made it difficult
+ to set a working "order_by" on a polymorphic mapper.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed a rather expensive call in Query that was slowing down
+ polymorphic queries.
+
+ .. change::
+ :tags: orm
+ :tickets: 954
+
+ "Passive defaults" and other "inline" defaults can now be
+ loaded during a flush() call if needed; in particular, this
+ allows constructing relations() where a foreign key column
+ references a server-side-generated, non-primary-key
+ column.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Additional Session transaction fixes/changes:
+ - Fixed bug with session transaction management: parent
+ transactions weren't started on the connection when
+ adding a connection to a nested transaction.
+
+ - session.transaction now always refers to the innermost
+ active transaction, even when commit/rollback are called
+ directly on the session transaction object.
+
+ - Two-phase transactions can now be prepared.
+
+ - When preparing a two-phase transaction fails on one
+ connection, all the connections are rolled back.
+
+ - session.close() didn't close all transactions when
+ nested transactions were used.
+
+ - rollback() previously erroneously set the current
+ transaction directly to the parent of the transaction
+ that could be rolled back to. Now it rolls back the next
+ transaction up that can handle it, but sets the current
+ transaction to it's parent and inactivates the
+ transactions in between. Inactive transactions can only
+ be rolled back or closed, any other call results in an
+ error.
+
+ - autoflush for commit() wasn't flushing for simple
+ subtransactions.
+
+ - unitofwork flush didn't close the failed transaction
+ when the session was not in a transaction and commiting
+ the transaction failed.
+
+ .. change::
+ :tags: orm
+ :tickets: 964, 940
+
+ Miscellaneous tickets:
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ Fixed a variety of hidden and some not-so-hidden
+ compatibility issues for Python 2.3, thanks to new support
+ for running the full test suite on 2.3.
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ Warnings are now issued as type exceptions.SAWarning.
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Better support for schemas in SQLite (linked in by ATTACH
+ DATABASE ... AS name). In some cases in the past, schema
+ names were ommitted from generated SQL for SQLite. This is
+ no longer the case.
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ table_names on SQLite now picks up temporary tables as well.
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Auto-detect an unspecified MySQL ANSI_QUOTES mode during
+ reflection operations, support for changing the mode
+ midstream. Manual mode setting is still required if no
+ reflection is used.
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Fixed reflection of TIME columns on SQLite.
+
+ .. change::
+ :tags: dialects
+ :tickets: 580
+
+ Finally added PGMacAddr type to postgres
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Reflect the sequence associated to a PK field (typically
+ with a BEFORE INSERT trigger) under Firebird
+
+ .. change::
+ :tags: dialects
+ :tickets: 941
+
+ Oracle assembles the correct columns in the result set
+ column mapping when generating a LIMIT/OFFSET subquery,
+ allows columns to map properly to result sets even if
+ long-name truncation kicks in
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ MSSQL now includes EXEC in the _is_select regexp, which
+ should allow row-returning stored procedures to be used.
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ MSSQL now includes an experimental implementation of
+ LIMIT/OFFSET using the ANSI SQL row_number() function, so it
+ requires MSSQL-2005 or higher. To enable the feature, add
+ "has_window_funcs" to the keyword arguments for connect, or
+ add "?has_window_funcs=1" to your dburi query arguments.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ Changed ext.activemapper to use a non-transactional session
+ for the objectstore.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ Fixed output order of "['a'] + obj.proxied" binary operation
+ on association-proxied lists.
+
+.. changelog::
+ :version: 0.4.2p3
+ :released: Wed Jan 09 2008
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ sub version numbering scheme changed to suite
+ setuptools version number rules; easy_install -u
+ should now get this version over 0.4.2.
+
+ .. change::
+ :tags: sql
+ :tickets: 912
+
+ Text type is properly exported now and does not
+ raise a warning on DDL create; String types with no
+ length only raise warnings during CREATE TABLE
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ new UnicodeText type is added, to specify an
+ encoded, unlengthed Text type
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fixed bug in union() so that select() statements
+ which don't derive from FromClause objects can be
+ unioned
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed bug with session.dirty when using "mutable
+ scalars" (such as PickleTypes)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added a more descriptive error message when flushing
+ on a relation() that has non-locally-mapped columns
+ in its primary or secondary join condition
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Fixed reflection of mysql empty string column
+ defaults.
+
+ .. change::
+ :tags: sql
+ :tickets: 912
+
+ changed name of TEXT to Text since its a "generic"
+ type; TEXT name is deprecated until 0.5. The
+ "upgrading" behavior of String to Text when no
+ length is present is also deprecated until 0.5; will
+ issue a warning when used for CREATE TABLE
+ statements (String with no length for SQL expression
+ purposes is still fine)
+
+ .. change::
+ :tags: sql
+ :tickets: 924
+
+ generative select.order_by(None) / group_by(None)
+ was not managing to reset order by/group by
+ criterion, fixed
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ suppressing *all* errors in
+ InstanceState.__cleanup() now.
+
+ .. change::
+ :tags: orm
+ :tickets: 922
+
+ fixed an attribute history bug whereby assigning a
+ new collection to a collection-based attribute which
+ already had pending changes would generate incorrect
+ history
+
+ .. change::
+ :tags: orm
+ :tickets: 925
+
+ fixed delete-orphan cascade bug whereby setting the
+ same object twice to a scalar attribute could log it
+ as an orphan
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed cascades on a += assignment to a list-based
+ relation.
+
+ .. change::
+ :tags: orm
+ :tickets: 919
+
+ synonyms can now be created against props that don't
+ exist yet, which are later added via add_property().
+ This commonly includes backrefs. (i.e. you can make
+ synonyms for backrefs without worrying about the
+ order of operations)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed bug which could occur with polymorphic "union"
+ mapper which falls back to "deferred" loading of
+ inheriting tables
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the "columns" collection on a mapper/mapped class
+ (i.e. 'c') is against the mapped table, not the
+ select_table in the case of polymorphic "union"
+ loading (this shouldn't be noticeable).
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ '+', '*', '+=' and '*=' support for association
+ proxied lists.
+
+ .. change::
+ :tags: dialects
+ :tickets: 923
+
+ mssql - narrowed down the test for "date"/"datetime"
+ in MSDate/ MSDateTime subclasses so that incoming
+ "datetime" objects don't get mis-interpreted as
+ "date" objects and vice versa.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed fairly critical bug whereby the same instance could be listed
+ more than once in the unitofwork.new collection; most typically
+ reproduced when using a combination of inheriting mappers and
+ ScopedSession.mapper, as the multiple __init__ calls per instance
+ could save() the object with distinct _state objects
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added very rudimentary yielding iterator behavior to Query. Call
+ query.yield_per(<number of rows>) and evaluate the Query in an
+ iterative context; every collection of N rows will be packaged up
+ and yielded. Use this method with extreme caution since it does
+ not attempt to reconcile eagerly loaded collections across
+ result batch boundaries, nor will it behave nicely if the same
+ instance occurs in more than one batch. This means that an eagerly
+ loaded collection will get cleared out if it's referenced in more than
+ one batch, and in all cases attributes will be overwritten on instances
+ that occur in more than one batch.
+
+ .. change::
+ :tags: orm
+ :tickets: 920
+
+ Fixed in-place set mutation operators for set collections and association
+ proxied sets.
+
+ .. change::
+ :tags: dialects
+ :tickets: 913
+
+ Fixed the missing call to subtype result processor for the PGArray
+ type.
+
+.. changelog::
+ :version: 0.4.2
+ :released: Wed Jan 02 2008
+
+ .. change::
+ :tags: sql
+ :tickets: 615
+
+ generic functions ! we introduce a database of known SQL functions, such
+ as current_timestamp, coalesce, and create explicit function objects
+ representing them. These objects have constrained argument lists, are
+ type aware, and can compile in a dialect-specific fashion. So saying
+ func.char_length("foo", "bar") raises an error (too many args),
+ func.coalesce(datetime.date(2007, 10, 5), datetime.date(2005, 10, 15))
+ knows that its return type is a Date. We only have a few functions
+ represented so far but will continue to add to the system
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ auto-reconnect support improved; a Connection can now automatically
+ reconnect after its underlying connection is invalidated, without
+ needing to connect() again from the engine. This allows an ORM session
+ bound to a single Connection to not need a reconnect.
+ Open transactions on the Connection must be rolled back after an invalidation
+ of the underlying connection else an error is raised. Also fixed
+ bug where disconnect detect was not being called for cursor(), rollback(),
+ or commit().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added new flag to String and create_engine(),
+ assert_unicode=(True|False|'warn'|None). Defaults to `False` or `None` on
+ create_engine() and String, `'warn'` on the Unicode type. When `True`,
+ results in all unicode conversion operations raising an exception when a
+ non-unicode bytestring is passed as a bind parameter. 'warn' results
+ in a warning. It is strongly advised that all unicode-aware applications
+ make proper use of Python unicode objects (i.e. u'hello' and not 'hello')
+ so that data round trips accurately.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ generation of "unique" bind parameters has been simplified to use the same
+ "unique identifier" mechanisms as everything else. This doesn't affect
+ user code, except any code that might have been hardcoded against the generated
+ names. Generated bind params now have the form "<paramname>_<num>",
+ whereas before only the second bind of the same name would have this form.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ select().as_scalar() will raise an exception if the select does not have
+ exactly one expression in its columns clause.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ bindparam() objects themselves can be used as keys for execute(), i.e.
+ statement.execute({bind1:'foo', bind2:'bar'})
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added new methods to TypeDecorator, process_bind_param() and
+ process_result_value(), which automatically take advantage of the processing
+ of the underlying type. Ideal for using with Unicode or Pickletype.
+ TypeDecorator should now be the primary way to augment the behavior of any
+ existing type including other TypeDecorator subclasses such as PickleType.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ selectables (and others) will issue a warning when two columns in
+ their exported columns collection conflict based on name.
+
+ .. change::
+ :tags: sql
+ :tickets: 890
+
+ tables with schemas can still be used in sqlite, firebird,
+ schema name just gets dropped
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ changed the various "literal" generation functions to use an anonymous
+ bind parameter. not much changes here except their labels now look
+ like ":param_1", ":param_2" instead of ":literal"
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ column labels in the form "tablename.columname", i.e. with a dot, are now
+ supported.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ from_obj keyword argument to select() can be a scalar or a list.
+
+ .. change::
+ :tags: orm
+ :tickets: 871
+
+ a major behavioral change to collection-based backrefs: they no
+ longer trigger lazy loads ! "reverse" adds and removes
+ are queued up and are merged with the collection when it is
+ actually read from and loaded; but do not trigger a load beforehand.
+ For users who have noticed this behavior, this should be much more
+ convenient than using dynamic relations in some cases; for those who
+ have not, you might notice your apps using a lot fewer queries than
+ before in some situations.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ mutable primary key support is added. primary key columns can be
+ changed freely, and the identity of the instance will change upon
+ flush. In addition, update cascades of foreign key referents (primary
+ key or not) along relations are supported, either in tandem with the
+ database's ON UPDATE CASCADE (required for DB's like Postgres) or
+ issued directly by the ORM in the form of UPDATE statements, by setting
+ the flag "passive_cascades=False".
+
+ .. change::
+ :tags: orm
+ :tickets: 490
+
+ inheriting mappers now inherit the MapperExtensions of their parent
+ mapper directly, so that all methods for a particular MapperExtension
+ are called for subclasses as well. As always, any MapperExtension
+ can return either EXT_CONTINUE to continue extension processing
+ or EXT_STOP to stop processing. The order of mapper resolution is:
+ <extensions declared on the classes mapper> <extensions declared on the
+ classes' parent mapper> <globally declared extensions>.
+
+ Note that if you instantiate the same extension class separately
+ and then apply it individually for two mappers in the same inheritance
+ chain, the extension will be applied twice to the inheriting class,
+ and each method will be called twice.
+
+ To apply a mapper extension explicitly to each inheriting class but
+ have each method called only once per operation, use the same
+ instance of the extension for both mappers.
+
+ .. change::
+ :tags: orm
+ :tickets: 907
+
+ MapperExtension.before_update() and after_update() are now called
+ symmetrically; previously, an instance that had no modified column
+ attributes (but had a relation() modification) could be called with
+ before_update() but not after_update()
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ columns which are missing from a Query's select statement
+ now get automatically deferred during load.
+
+ .. change::
+ :tags: orm
+ :tickets: 908
+
+ mapped classes which extend "object" and do not provide an
+ __init__() method will now raise TypeError if non-empty *args
+ or **kwargs are present at instance construction time (and are
+ not consumed by any extensions such as the scoped_session mapper),
+ consistent with the behavior of normal Python classes
+
+ .. change::
+ :tags: orm
+ :tickets: 899
+
+ fixed Query bug when filter_by() compares a relation against None
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ improved support for pickling of mapped entities. Per-instance
+ lazy/deferred/expired callables are now serializable so that
+ they serialize and deserialize with _state.
+
+ .. change::
+ :tags: orm
+ :tickets: 801
+
+ new synonym() behavior: an attribute will be placed on the mapped
+ class, if one does not exist already, in all cases. if a property
+ already exists on the class, the synonym will decorate the property
+ with the appropriate comparison operators so that it can be used in in
+ column expressions just like any other mapped attribute (i.e. usable in
+ filter(), etc.) the "proxy=True" flag is deprecated and no longer means
+ anything. Additionally, the flag "map_column=True" will automatically
+ generate a ColumnProperty corresponding to the name of the synonym,
+ i.e.: 'somename':synonym('_somename', map_column=True) will map the
+ column named 'somename' to the attribute '_somename'. See the example
+ in the mapper docs.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.select_from() now replaces all existing FROM criterion with
+ the given argument; the previous behavior of constructing a list
+ of FROM clauses was generally not useful as is required
+ filter() calls to create join criterion, and new tables introduced
+ within filter() already add themselves to the FROM clause. The
+ new behavior allows not just joins from the main table, but select
+ statements as well. Filter criterion, order bys, eager load
+ clauses will be "aliased" against the given statement.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ this month's refactoring of attribute instrumentation changes
+ the "copy-on-load" behavior we've had since midway through 0.3
+ with "copy-on-modify" in most cases. This takes a sizable chunk
+ of latency out of load operations and overall does less work
+ as only attributes which are actually modified get their
+ "committed state" copied. Only "mutable scalar" attributes
+ (i.e. a pickled object or other mutable item), the reason for
+ the copy-on-load change in the first place, retain the old
+ behavior.
+
+ .. change::
+ :tags: attrname, orm
+ :tickets:
+
+ a slight behavioral change to attributes is, del'ing an attribute
+ does *not* cause the lazyloader of that attribute to fire off again;
+ the "del" makes the effective value of the attribute "None". To
+ re-trigger the "loader" for an attribute, use
+ session.expire(instance,).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.filter(SomeClass.somechild == None), when comparing
+ a many-to-one property to None, properly generates "id IS NULL"
+ including that the NULL is on the right side.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.order_by() takes into account aliased joins, i.e.
+ query.join('orders', aliased=True).order_by(Order.id)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ eagerload(), lazyload(), eagerload_all() take an optional
+ second class-or-mapper argument, which will select the mapper
+ to apply the option towards. This can select among other
+ mappers which were added using add_entity().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ eagerloading will work with mappers added via add_entity().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added "cascade delete" behavior to "dynamic" relations just like
+ that of regular relations. if passive_deletes flag (also just added)
+ is not set, a delete of the parent item will trigger a full load of
+ the child items so that they can be deleted or updated accordingly.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ also with dynamic, implemented correct count() behavior as well
+ as other helper methods.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fix to cascades on polymorphic relations, such that cascades
+ from an object to a polymorphic collection continue cascading
+ along the set of attributes specific to each element in the collection.
+
+ .. change::
+ :tags: orm
+ :tickets: 893
+
+ query.get() and query.load() do not take existing filter or other
+ criterion into account; these methods *always* look up the given id
+ in the database or return the current instance from the identity map,
+ disregarding any existing filter, join, group_by or other criterion
+ which has been configured.
+
+ .. change::
+ :tags: orm
+ :tickets: 883
+
+ added support for version_id_col in conjunction with inheriting mappers.
+ version_id_col is typically set on the base mapper in an inheritance
+ relationship where it takes effect for all inheriting mappers.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ relaxed rules on column_property() expressions having labels; any
+ ColumnElement is accepted now, as the compiler auto-labels non-labeled
+ ColumnElements now. a selectable, like a select() statement, still
+ requires conversion to ColumnElement via as_scalar() or label().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed backref bug where you could not del instance.attr if attr
+ was None
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ several ORM attributes have been removed or made private:
+ mapper.get_attr_by_column(), mapper.set_attr_by_column(),
+ mapper.pks_by_table, mapper.cascade_callable(),
+ MapperProperty.cascade_callable(), mapper.canload(),
+ mapper.save_obj(), mapper.delete_obj(), mapper._mapper_registry,
+ attributes.AttributeManager
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Assigning an incompatible collection type to a relation attribute now
+ raises TypeError instead of sqlalchemy's ArgumentError.
+
+ .. change::
+ :tags: orm
+ :tickets: 886
+
+ Bulk assignment of a MappedCollection now raises an error if a key in the
+ incoming dictionary does not match the key that the collection's keyfunc
+ would use for that value.
+
+ .. change::
+ :tags: orm, newval1, newval2
+ :tickets:
+
+ Custom collections can now specify a @converter method to translate
+ objects used in "bulk" assignment into a stream of values, as in::
+
+ obj.col =
+ # or
+ obj.dictcol = {'foo': newval1, 'bar': newval2}
+
+ The MappedCollection uses this hook to ensure that incoming key/value
+ pairs are sane from the collection's perspective.
+
+ .. change::
+ :tags: orm
+ :tickets: 872
+
+ fixed endless loop issue when using lazy="dynamic" on both
+ sides of a bi-directional relationship
+
+ .. change::
+ :tags: orm
+ :tickets: 904
+
+ more fixes to the LIMIT/OFFSET aliasing applied with Query + eagerloads,
+ in this case when mapped against a select statement
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fix to self-referential eager loading such that if the same mapped
+ instance appears in two or more distinct sets of columns in the same
+ result set, its eagerly loaded collection will be populated regardless
+ of whether or not all of the rows contain a set of "eager" columns for
+ that collection. this would also show up as a KeyError when fetching
+ results with join_depth turned on.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed bug where Query would not apply a subquery to the SQL when LIMIT
+ was used in conjunction with an inheriting mapper where the eager
+ loader was only in the parent mapper.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ clarified the error message which occurs when you try to update()
+ an instance with the same identity key as an instance already present
+ in the session.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ some clarifications and fixes to merge(instance, dont_load=True).
+ fixed bug where lazy loaders were getting disabled on returned instances.
+ Also, we currently do not support merging an instance which has uncommitted
+ changes on it, in the case that dont_load=True is used....this will
+ now raise an error. This is due to complexities in merging the
+ "committed state" of the given instance to correctly correspond to the
+ newly copied instance, as well as other modified state.
+ Since the use case for dont_load=True is caching, the given instances
+ shouldn't have any uncommitted changes on them anyway.
+ We also copy the instances over without using any events now, so that
+ the 'dirty' list on the new session remains unaffected.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed bug which could arise when using session.begin_nested() in conjunction
+ with more than one level deep of enclosing session.begin() statements
+
+ .. change::
+ :tags: orm
+ :tickets: 914
+
+ fixed session.refresh() with instance that has custom entity_name
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ sqlite SLDate type will not erroneously render "microseconds" portion
+ of a datetime or time object.
+
+ .. change::
+ :tags: dialects
+ :tickets: 902
+
+ oracle
+ - added disconnect detection support for Oracle
+ - some cleanup to binary/raw types so that cx_oracle.LOB is detected
+ on an ad-hoc basis
+
+ .. change::
+ :tags: dialects
+ :tickets: 824, 839, 842, 901
+
+ MSSQL
+ - PyODBC no longer has a global "set nocount on".
+ - Fix non-identity integer PKs on autload
+ - Better support for convert_unicode
+ - Less strict date conversion for pyodbc/adodbapi
+ - Schema-qualified tables / autoload
+
+ .. change::
+ :tags: firebird, backend
+ :tickets: 410
+
+ does properly reflect domains (partially fixing) and
+ PassiveDefaults
+
+ .. change::
+ :tags: 3562, firebird, backend
+ :tickets:
+
+ reverted to use default poolclass (was set to SingletonThreadPool in
+ 0.4.0 for test purposes)
+
+ .. change::
+ :tags: firebird, backend
+ :tickets:
+
+ map func.length() to 'char_length' (easily overridable with the UDF
+ 'strlen' on old versions of Firebird)
+
+.. changelog::
+ :version: 0.4.1
+ :released: Sun Nov 18 2007
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the "shortname" keyword parameter on bindparam() has been
+ deprecated.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added contains operator (generates a "LIKE %<other>%" clause).
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ anonymous column expressions are automatically labeled.
+ e.g. select([x* 5]) produces "SELECT x * 5 AS anon_1".
+ This allows the labelname to be present in the cursor.description
+ which can then be appropriately matched to result-column processing
+ rules. (we can't reliably use positional tracking for result-column
+ matches since text() expressions may represent multiple columns).
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ operator overloading is now controlled by TypeEngine objects - the
+ one built-in operator overload so far is String types overloading
+ '+' to be the string concatenation operator.
+ User-defined types can also define their own operator overloading
+ by overriding the adapt_operator(self, op) method.
+
+ .. change::
+ :tags: sql
+ :tickets: 819
+
+ untyped bind parameters on the right side of a binary expression
+ will be assigned the type of the left side of the operation, to better
+ enable the appropriate bind parameter processing to take effect
+
+ .. change::
+ :tags: sql
+ :tickets: 833
+
+ Removed regular expression step from most statement compilations.
+ Also fixes
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed empty (zero column) sqlite inserts, allowing inserts on
+ autoincrementing single column tables.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed expression translation of text() clauses; this repairs various
+ ORM scenarios where literal text is used for SQL expressions
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Removed ClauseParameters object; compiled.params returns a regular
+ dictionary now, as well as result.last_inserted_params() /
+ last_updated_params().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed INSERT statements w.r.t. primary key columns that have
+ SQL-expression based default generators on them; SQL expression
+ executes inline as normal but will not trigger a "postfetch" condition
+ for the column, for those DB's who provide it via cursor.lastrowid
+
+ .. change::
+ :tags: sql
+ :tickets: 844
+
+ func. objects can be pickled/unpickled
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ rewrote and simplified the system used to "target" columns across
+ selectable expressions. On the SQL side this is represented by the
+ "corresponding_column()" method. This method is used heavily by the ORM
+ to "adapt" elements of an expression to similar, aliased expressions,
+ as well as to target result set columns originally bound to a
+ table or selectable to an aliased, "corresponding" expression. The new
+ rewrite features completely consistent and accurate behavior.
+
+ .. change::
+ :tags: sql
+ :tickets: 573
+
+ Added a field ("info") for storing arbitrary data on schema items
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The "properties" collection on Connections has been renamed "info" to
+ match schema's writable collections. Access is still available via
+ the "properties" name until 0.5.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fixed the close() method on Transaction when using strategy='threadlocal'
+
+ .. change::
+ :tags: sql
+ :tickets: 853
+
+ fix to compiled bind parameters to not mistakenly populate None
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ <Engine|Connection>._execute_clauseelement becomes a public method
+ Connectable.execute_clauseelement
+
+ .. change::
+ :tags: orm
+ :tickets: 843
+
+ eager loading with LIMIT/OFFSET applied no longer adds the primary
+ table joined to a limited subquery of itself; the eager loads now
+ join directly to the subquery which also provides the primary table's
+ columns to the result set. This eliminates a JOIN from all eager loads
+ with LIMIT/OFFSET.
+
+ .. change::
+ :tags: orm
+ :tickets: 802
+
+ session.refresh() and session.expire() now support an additional argument
+ "attribute_names", a list of individual attribute keynames to be refreshed
+ or expired, allowing partial reloads of attributes on an already-loaded
+ instance.
+
+ .. change::
+ :tags: orm
+ :tickets: 767
+
+ added op() operator to instrumented attributes; i.e.
+ User.name.op('ilike')('%somename%')
+
+ .. change::
+ :tags: orm
+ :tickets: 676
+
+ Mapped classes may now define __eq__, __hash__, and __nonzero__ methods
+ with arbitrary semantics. The orm now handles all mapped instances on
+ an identity-only basis. (e.g. 'is' vs '==')
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the "properties" accessor on Mapper is removed; it now throws an informative
+ exception explaining the usage of mapper.get_property() and
+ mapper.iterate_properties
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added having() method to Query, applies HAVING to the generated statement
+ in the same way as filter() appends to the WHERE clause.
+
+ .. change::
+ :tags: orm
+ :tickets: 777
+
+ The behavior of query.options() is now fully based on paths, i.e. an
+ option such as eagerload_all('x.y.z.y.x') will apply eagerloading to
+ only those paths, i.e. and not 'x.y.x'; eagerload('children.children')
+ applies only to exactly two-levels deep, etc.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ PickleType will compare using `==` when set up with mutable=False,
+ and not the `is` operator. To use `is` or any other comparator, send
+ in a custom comparison function using PickleType(comparator=my_custom_comparator).
+
+ .. change::
+ :tags: orm
+ :tickets: 848
+
+ query doesn't throw an error if you use distinct() and an order_by()
+ containing UnaryExpressions (or other) together
+
+ .. change::
+ :tags: orm
+ :tickets: 786
+
+ order_by() expressions from joined tables are properly added to columns
+ clause when using distinct()
+
+ .. change::
+ :tags: orm
+ :tickets: 858
+
+ fixed error where Query.add_column() would not accept a class-bound
+ attribute as an argument; Query also raises an error if an invalid
+ argument was sent to add_column() (at instances() time)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added a little more checking for garbage-collection dereferences in
+ InstanceState.__cleanup() to reduce "gc ignored" errors on app
+ shutdown
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The session API has been solidified:
+
+ .. change::
+ :tags: orm
+ :tickets: 840
+
+ It's an error to session.save() an object which is already
+ persistent
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ It's an error to session.delete() an object which is *not*
+ persistent.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ session.update() and session.delete() raise an error when updating
+ or deleting an instance that is already in the session with a
+ different identity.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The session checks more carefully when determining "object X already
+ in another session"; e.g. if you pickle a series of objects and
+ unpickle (i.e. as in a Pylons HTTP session or similar), they can go
+ into a new session without any conflict
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ merge() includes a keyword argument "dont_load=True". setting this
+ flag will cause the merge operation to not load any data from the
+ database in response to incoming detached objects, and will accept
+ the incoming detached object as though it were already present in
+ that session. Use this to merge detached objects from external
+ caching systems into the session.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Deferred column attributes no longer trigger a load operation when the
+ attribute is assigned to. In those cases, the newly assigned value
+ will be present in the flushes' UPDATE statement unconditionally.
+
+ .. change::
+ :tags: orm
+ :tickets: 834
+
+ Fixed a truncation error when re-assigning a subset of a collection
+ (obj.relation = obj.relation[1:])
+
+ .. change::
+ :tags: orm
+ :tickets: 832
+
+ De-cruftified backref configuration code, backrefs which step on
+ existing properties now raise an error
+
+ .. change::
+ :tags: orm
+ :tickets: 831
+
+ Improved behavior of add_property() etc., fixed involving
+ synonym/deferred.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed clear_mappers() behavior to better clean up after itself.
+
+ .. change::
+ :tags: orm
+ :tickets: 841
+
+ Fix to "row switch" behavior, i.e. when an INSERT/DELETE is combined
+ into a single UPDATE; many-to-many relations on the parent object
+ update properly.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed __hash__ for association proxy- these collections are unhashable,
+ just like their mutable Python counterparts.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added proxying of save_or_update, __contains__ and __iter__ methods for
+ scoped sessions.
+
+ .. change::
+ :tags: orm
+ :tickets: 852
+
+ fixed very hard-to-reproduce issue where by the FROM clause of Query
+ could get polluted by certain generative calls
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Added experimental support for MaxDB (versions >= 7.6.03.007 only).
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ oracle will now reflect "DATE" as an OracleDateTime column, not
+ OracleDate
+
+ .. change::
+ :tags: dialects
+ :tickets: 847
+
+ added awareness of schema name in oracle table_names() function,
+ fixes metadata.reflect(schema='someschema')
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ MSSQL anonymous labels for selection of functions made deterministic
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ sqlite will reflect "DECIMAL" as a numeric column.
+
+ .. change::
+ :tags: dialects
+ :tickets: 828
+
+ Made access dao detection more reliable
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Renamed the Dialect attribute 'preexecute_sequences' to
+ 'preexecute_pk_sequences'. An attribute porxy is in place for
+ out-of-tree dialects using the old name.
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Added test coverage for unknown type reflection. Fixed sqlite/mysql
+ handling of type reflection for unknown types.
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ Added REAL for mysql dialect (for folks exploiting the
+ REAL_AS_FLOAT sql mode).
+
+ .. change::
+ :tags: dialects
+ :tickets:
+
+ mysql Float, MSFloat and MSDouble constructed without arguments
+ now produce no-argument DDL, e.g.'FLOAT'.
+
+ .. change::
+ :tags: misc
+ :tickets:
+
+ Removed unused util.hash().
+
+.. changelog::
+ :version: 0.4.0
+ :released: Wed Oct 17 2007
+
+ .. change::
+ :tags:
+ :tickets:
+
+ (see 0.4.0beta1 for the start of major changes against 0.3,
+ as well as http://www.sqlalchemy.org/trac/wiki/WhatsNewIn04 )
+
+ .. change::
+ :tags:
+ :tickets: 785
+
+ Added initial Sybase support (mxODBC so far)
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added partial index support for PostgreSQL. Use the postgres_where keyword
+ on the Index.
+
+ .. change::
+ :tags:
+ :tickets: 817
+
+ string-based query param parsing/config file parser understands
+ wider range of string values for booleans
+
+ .. change::
+ :tags:
+ :tickets: 813
+
+ backref remove object operation doesn't fail if the other-side
+ collection doesn't contain the item, supports noload collections
+
+ .. change::
+ :tags:
+ :tickets: 818
+
+ removed __len__ from "dynamic" collection as it would require issuing
+ a SQL "count()" operation, thus forcing all list evaluations to issue
+ redundant SQL
+
+ .. change::
+ :tags:
+ :tickets: 816
+
+ inline optimizations added to locate_dirty() which can greatly speed up
+ repeated calls to flush(), as occurs with autoflush=True
+
+ .. change::
+ :tags:
+ :tickets:
+
+ The IdentifierPreprarer's _requires_quotes test is now regex based. Any
+ out-of-tree dialects that provide custom sets of legal_characters or
+ illegal_initial_characters will need to move to regexes or override
+ _requires_quotes.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Firebird has supports_sane_rowcount and supports_sane_multi_rowcount set
+ to False due to ticket #370 (right way).
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Improvements and fixes on Firebird reflection:
+ . FBDialect now mimics OracleDialect, regarding case-sensitivity of TABLE and
+ COLUMN names (see 'case_sensitive remotion' topic on this current file).
+ . FBDialect.table_names() doesn't bring system tables (ticket:796).
+ . FB now reflects Column's nullable property correctly.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Fixed SQL compiler's awareness of top-level column labels as used
+ in result-set processing; nested selects which contain the same column
+ names don't affect the result or conflict with result-column metadata.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ query.get() and related functions (like many-to-one lazyloading)
+ use compile-time-aliased bind parameter names, to prevent
+ name conflicts with bind parameters that already exist in the
+ mapped selectable.
+
+ .. change::
+ :tags:
+ :tickets: 795
+
+ Fixed three- and multi-level select and deferred inheritance loading
+ (i.e. abc inheritance with no select_table).
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Ident passed to id_chooser in shard.py always a list.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ The no-arg ResultProxy._row_processor() is now the class attribute
+ `_process_row`.
+
+ .. change::
+ :tags:
+ :tickets: 797
+
+ Added support for returning values from inserts and updates for
+ PostgreSQL 8.2+.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ PG reflection, upon seeing the default schema name being used explicitly
+ as the "schema" argument in a Table, will assume that this is the the
+ user's desired convention, and will explicitly set the "schema" argument
+ in foreign-key-related reflected tables, thus making them match only
+ with Table constructors that also use the explicit "schema" argument
+ (even though its the default schema).
+ In other words, SA assumes the user is being consistent in this usage.
+
+ .. change::
+ :tags:
+ :tickets: 808
+
+ fixed sqlite reflection of BOOL/BOOLEAN
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added support for UPDATE with LIMIT on mysql.
+
+ .. change::
+ :tags:
+ :tickets: 803
+
+ null foreign key on a m2o doesn't trigger a lazyload
+
+ .. change::
+ :tags:
+ :tickets: 800
+
+ oracle does not implicitly convert to unicode for non-typed result
+ sets (i.e. when no TypeEngine/String/Unicode type is even being used;
+ previously it was detecting DBAPI types and converting regardless).
+ should fix
+
+ .. change::
+ :tags:
+ :tickets: 806
+
+ fix to anonymous label generation of long table/column names
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Firebird dialect now uses SingletonThreadPool as poolclass.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Firebird now uses dialect.preparer to format sequences names
+
+ .. change::
+ :tags:
+ :tickets: 810
+
+ Fixed breakage with postgres and multiple two-phase transactions. Two-phase
+ commits and and rollbacks didn't automatically end up with a new transaction
+ as the usual dbapi commits/rollbacks do.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added an option to the _ScopedExt mapper extension to not automatically
+ save new objects to session on object initialization.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ fixed Oracle non-ansi join syntax
+
+ .. change::
+ :tags:
+ :tickets:
+
+ PickleType and Interval types (on db not supporting it natively) are now
+ slightly faster.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added Float and Time types to Firebird (FBFloat and FBTime). Fixed
+ BLOB SUB_TYPE for TEXT and Binary types.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Changed the API for the in_ operator. in_() now accepts a single argument
+ that is a sequence of values or a selectable. The old API of passing in
+ values as varargs still works but is deprecated.
+
+.. changelog::
+ :version: 0.4.0beta6
+ :released: Thu Sep 27 2007
+
+ .. change::
+ :tags:
+ :tickets:
+
+ The Session identity map is now *weak referencing* by default, use
+ weak_identity_map=False to use a regular dict. The weak dict we are using
+ is customized to detect instances which are "dirty" and maintain a
+ temporary strong reference to those instances until changes are flushed.
+
+ .. change::
+ :tags:
+ :tickets: 758
+
+ Mapper compilation has been reorganized such that most compilation occurs
+ upon mapper construction. This allows us to have fewer calls to
+ mapper.compile() and also to allow class-based properties to force a
+ compilation (i.e. User.addresses == 7 will compile all mappers; this is). The only caveat here is that an inheriting mapper now
+ looks for its inherited mapper upon construction; so mappers within
+ inheritance relationships need to be constructed in inheritance order
+ (which should be the normal case anyway).
+
+ .. change::
+ :tags:
+ :tickets:
+
+ added "FETCH" to the keywords detected by Postgres to indicate a
+ result-row holding statement (i.e. in addition to "SELECT").
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added full list of SQLite reserved keywords so that they get escaped
+ properly.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Tightened up the relationship between the Query's generation of "eager
+ load" aliases, and Query.instances() which actually grabs the eagerly
+ loaded rows. If the aliases were not specifically generated for that
+ statement by EagerLoader, the EagerLoader will not take effect when the
+ rows are fetched. This prevents columns from being grabbed accidentally
+ as being part of an eager load when they were not meant for such, which
+ can happen with textual SQL as well as some inheritance situations. It's
+ particularly important since the "anonymous aliasing" of columns uses
+ simple integer counts now to generate labels.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Removed "parameters" argument from clauseelement.compile(), replaced with
+ "column_keys". The parameters sent to execute() only interact with the
+ insert/update statement compilation process in terms of the column names
+ present but not the values for those columns. Produces more consistent
+ execute/executemany behavior, simplifies things a bit internally.
+
+ .. change::
+ :tags:
+ :tickets: 560
+
+ Added 'comparator' keyword argument to PickleType. By default, "mutable"
+ PickleType does a "deep compare" of objects using their dumps()
+ representation. But this doesn't work for dictionaries. Pickled objects
+ which provide an adequate __eq__() implementation can be set up with
+ "PickleType(comparator=operator.eq)"
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added session.is_modified(obj) method; performs the same "history"
+ comparison operation as occurs within a flush operation; setting
+ include_collections=False gives the same result as is used when the flush
+ determines whether or not to issue an UPDATE for the instance's row.
+
+ .. change::
+ :tags:
+ :tickets: 584, 761
+
+ Added "schema" argument to Sequence; use this with Postgres /Oracle when
+ the sequence is located in an alternate schema. Implements part of, should fix.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Fixed reflection of the empty string for mysql enums.
+
+ .. change::
+ :tags:
+ :tickets: 794
+
+ Changed MySQL dialect to use the older LIMIT <offset>, <limit> syntax
+ instead of LIMIT <l> OFFSET <o> for folks using 3.23.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added 'passive_deletes="all"' flag to relation(), disables all nulling-out
+ of foreign key attributes during a flush where the parent object is
+ deleted.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Column defaults and onupdates, executing inline, will add parenthesis for
+ subqueries and other parenthesis-requiring expressions
+
+ .. change::
+ :tags:
+ :tickets: 793
+
+ The behavior of String/Unicode types regarding that they auto-convert to
+ TEXT/CLOB when no length is present now occurs *only* for an exact type of
+ String or Unicode with no arguments. If you use VARCHAR or NCHAR
+ (subclasses of String/Unicode) with no length, they will be interpreted by
+ the dialect as VARCHAR/NCHAR; no "magic" conversion happens there. This
+ is less surprising behavior and in particular this helps Oracle keep
+ string-based bind parameters as VARCHARs and not CLOBs.
+
+ .. change::
+ :tags:
+ :tickets: 771
+
+ Fixes to ShardedSession to work with deferred columns.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ User-defined shard_chooser() function must accept "clause=None" argument;
+ this is the ClauseElement passed to session.execute(statement) and can be
+ used to determine correct shard id (since execute() doesn't take an
+ instance.)
+
+ .. change::
+ :tags:
+ :tickets: 764
+
+ Adjusted operator precedence of NOT to match '==' and others, so that
+ ~(x <operator> y) produces NOT (x <op> y), which is better compatible
+ with older MySQL versions.. This doesn't apply to "~(x==y)"
+ as it does in 0.3 since ~(x==y) compiles to "x != y", but still applies
+ to operators like BETWEEN.
+
+ .. change::
+ :tags:
+ :tickets: 757, 768, 779, 728
+
+ Other tickets:,,.
+
+.. changelog::
+ :version: 0.4.0beta5
+ :released:
+
+ .. change::
+ :tags:
+ :tickets: 754
+
+ Connection pool fixes; the better performance of beta4 remains but fixes
+ "connection overflow" and other bugs which were present (like).
+
+ .. change::
+ :tags:
+ :tickets: 769
+
+ Fixed bugs in determining proper sync clauses from custom inherit
+ conditions.
+
+ .. change::
+ :tags:
+ :tickets: 763
+
+ Extended 'engine_from_config' coercion for QueuePool size / overflow.
+
+ .. change::
+ :tags:
+ :tickets: 748
+
+ mysql views can be reflected again.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ AssociationProxy can now take custom getters and setters.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Fixed malfunctioning BETWEEN in orm queries.
+
+ .. change::
+ :tags:
+ :tickets: 762
+
+ Fixed OrderedProperties pickling
+
+ .. change::
+ :tags:
+ :tickets:
+
+ SQL-expression defaults and sequences now execute "inline" for all
+ non-primary key columns during an INSERT or UPDATE, and for all columns
+ during an executemany()-style call. inline=True flag on any insert/update
+ statement also forces the same behavior with a single execute().
+ result.postfetch_cols() is a collection of columns for which the previous
+ single insert or update statement contained a SQL-side default expression.
+
+ .. change::
+ :tags:
+ :tickets: 759
+
+ Fixed PG executemany() behavior.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ postgres reflects tables with autoincrement=False for primary key columns
+ which have no defaults.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ postgres no longer wraps executemany() with individual execute() calls,
+ instead favoring performance. "rowcount"/"concurrency" checks with
+ deleted items (which use executemany) are disabled with PG since psycopg2
+ does not report proper rowcount for executemany().
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 742
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 748
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 760
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 762
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 763
+
+
+
+.. changelog::
+ :version: 0.4.0beta4
+ :released: Wed Aug 22 2007
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Tidied up what ends up in your namespace when you 'from sqlalchemy import *':
+
+ .. change::
+ :tags:
+ :tickets:
+
+ 'table' and 'column' are no longer imported. They remain available by
+ direct reference (as in 'sql.table' and 'sql.column') or a glob import
+ from the sql package. It was too easy to accidentally use a
+ sql.expressions.table instead of schema.Table when just starting out
+ with SQLAlchemy, likewise column.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Internal-ish classes like ClauseElement, FromClause, NullTypeEngine,
+ etc., are also no longer imported into your namespace
+
+ .. change::
+ :tags:
+ :tickets:
+
+ The 'Smallinteger' compatiblity name (small i!) is no longer imported,
+ but remains in schema.py for now. SmallInteger (big I!) is still
+ imported.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ The connection pool uses a "threadlocal" strategy internally to return
+ the same connection already bound to a thread, for "contextual" connections;
+ these are the connections used when you do a "connectionless" execution
+ like insert().execute(). This is like a "partial" version of the
+ "threadlocal" engine strategy but without the thread-local transaction part
+ of it. We're hoping it reduces connection pool overhead as well as
+ database usage. However, if it proves to impact stability in a negative way,
+ we'll roll it right back.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Fix to bind param processing such that "False" values (like blank strings)
+ still get processed/encoded.
+
+ .. change::
+ :tags:
+ :tickets: 752
+
+ Fix to select() "generative" behavior, such that calling column(),
+ select_from(), correlate(), and with_prefix() does not modify the
+ original select object
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added a "legacy" adapter to types, such that user-defined TypeEngine
+ and TypeDecorator classes which define convert_bind_param() and/or
+ convert_result_value() will continue to function. Also supports
+ calling the super() version of those methods.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added session.prune(), trims away instances cached in a session that
+ are no longer referenced elsewhere. (A utility for strong-ref
+ identity maps).
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added close() method to Transaction. Closes out a transaction using
+ rollback if it's the outermost transaction, otherwise just ends
+ without affecting the outer transaction.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Transactional and non-transactional Session integrates better with
+ bound connection; a close() will ensure that connection
+ transactional state is the same as that which existed on it before
+ being bound to the Session.
+
+ .. change::
+ :tags:
+ :tickets: 735
+
+ Modified SQL operator functions to be module-level operators,
+ allowing SQL expressions to be pickleable.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Small adjustment to mapper class.__init__ to allow for Py2.6
+ object.__init__() behavior.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Fixed 'prefix' argument for select()
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Connection.begin() no longer accepts nested=True, this logic is now
+ all in begin_nested().
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Fixes to new "dynamic" relation loader involving cascades
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 735
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 752
+
+
+
+.. changelog::
+ :version: 0.4.0beta3
+ :released: Thu Aug 16 2007
+
+ .. change::
+ :tags:
+ :tickets:
+
+ SQL types optimization:
+
+ .. change::
+ :tags:
+ :tickets:
+
+ New performance tests show a combined mass-insert/mass-select test as
+ having 68% fewer function calls than the same test run against 0.3.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ General performance improvement of result set iteration is around 10-20%.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ In types.AbstractType, convert_bind_param() and convert_result_value()
+ have migrated to callable-returning bind_processor() and
+ result_processor() methods. If no callable is returned, no pre/post
+ processing function is called.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Hooks added throughout base/sql/defaults to optimize the calling of bind
+ aram/result processors so that method call overhead is minimized.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Support added for executemany() scenarios such that unneeded "last row id"
+ logic doesn't kick in, parameters aren't excessively traversed.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added 'inherit_foreign_keys' arg to mapper().
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Added support for string date passthrough in sqlite.
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 738
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 739
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 743
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 744
+
+
+
+.. changelog::
+ :version: 0.4.0beta2
+ :released: Tue Aug 14 2007
+
+ .. change::
+ :tags: oracle, improvements.
+ :tickets:
+
+ Auto-commit after LOAD DATA INFILE for mysql.
+
+ .. change::
+ :tags: oracle, improvements.
+ :tickets:
+
+ A rudimental SessionExtension class has been added, allowing user-defined
+ functionality to take place at flush(), commit(), and rollback() boundaries.
+
+ .. change::
+ :tags: oracle, improvements.
+ :tickets:
+
+ Added engine_from_config() function for helping to create_engine() from an
+ .ini style config.
+
+ .. change::
+ :tags: oracle, improvements.
+ :tickets:
+
+ base_mapper() becomes a plain attribute.
+
+ .. change::
+ :tags: oracle, improvements.
+ :tickets:
+
+ session.execute() and scalar() can search for a Table with which to bind from
+ using the given ClauseElement.
+
+ .. change::
+ :tags: oracle, improvements.
+ :tickets:
+
+ Session automatically extrapolates tables from mappers with binds, also uses
+ base_mapper so that inheritance hierarchies bind automatically.
+
+ .. change::
+ :tags: oracle, improvements.
+ :tickets:
+
+ Moved ClauseVisitor traversal back to inlined non-recursive.
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 730
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 732
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 733
+
+
+
+ .. change::
+ :tags: tickets, fixed
+ :tickets: 734
+
+
+
+.. changelog::
+ :version: 0.4.0beta1
+ :released: Sun Aug 12 2007
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Speed! Along with recent speedups to ResultProxy, total number of function
+ calls significantly reduced for large loads.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ test/perf/masseagerload.py reports 0.4 as having the fewest number of
+ function calls across all SA versions (0.1, 0.2, and 0.3).
+
+ .. change::
+ :tags: orm
+ :tickets: 213
+
+ New collection_class api and implementation. Collections are
+ now instrumented via decorations rather than proxying. You can now have
+ collections that manage their own membership, and your class instance will
+ be directly exposed on the relation property. The changes are transparent
+ for most users.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ InstrumentedList (as it was) is removed, and relation properties no
+ longer have 'clear()', '.data', or any other added methods beyond those
+ provided by the collection type. You are free, of course, to add them to
+ a custom class.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ __setitem__-like assignments now fire remove events for the existing
+ value, if any.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ dict-likes used as collection classes no longer need to change __iter__
+ semantics- itervalues() is used by default instead. This is a backwards
+ incompatible change.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Subclassing dict for a mapped collection is no longer needed in most
+ cases. orm.collections provides canned implementations that key objects
+ by a specified column or a custom function of your choice.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Collection assignment now requires a compatible type- assigning None to
+ clear a collection or assigning a list to a dict collection will now
+ raise an argument error.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ AttributeExtension moved to interfaces, and .delete is now .remove The
+ event method signature has also been swapped around.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Major overhaul for Query:
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ All selectXXX methods are deprecated. Generative methods are now the
+ standard way to do things, i.e. filter(), filter_by(), all(), one(),
+ etc. Deprecated methods are docstring'ed with their new replacements.
+
+ .. change::
+ :tags: orm
+ :tickets: 643
+
+ Class-level properties are now usable as query elements... no more
+ '.c.'! "Class.c.propname" is now superceded by "Class.propname". All
+ clause operators are supported, as well as higher level operators such
+ as Class.prop==<some instance> for scalar attributes,
+ Class.prop.contains(<some instance>) and Class.prop.any(<some
+ expression>) for collection-based attributes (all are also
+ negatable). Table-based column expressions as well as columns mounted
+ on mapped classes via 'c' are of course still fully available and can be
+ freely mixed with the new attributes.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Removed ancient query.select_by_attributename() capability.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The aliasing logic used by eager loading has been generalized, so that
+ it also adds full automatic aliasing support to Query. It's no longer
+ necessary to create an explicit Alias to join to the same tables
+ multiple times; *even for self-referential relationships*.
+
+ - join() and outerjoin() take arguments "aliased=True". Yhis causes
+ their joins to be built on aliased tables; subsequent calls to
+ filter() and filter_by() will translate all table expressions (yes,
+ real expressions using the original mapped Table) to be that of the
+ Alias for the duration of that join() (i.e. until reset_joinpoint() or
+ another join() is called).
+
+ - join() and outerjoin() take arguments "id=<somestring>". When used
+ with "aliased=True", the id can be referenced by add_entity(cls,
+ id=<somestring>) so that you can select the joined instances even if
+ they're from an alias.
+
+ - join() and outerjoin() now work with self-referential relationships!
+ Using "aliased=True", you can join as many levels deep as desired,
+ i.e. query.join(['children', 'children'], aliased=True); filter
+ criterion will be against the rightmost joined table
+
+ .. change::
+ :tags: orm
+ :tickets: 660
+
+ Added query.populate_existing(), marks the query to reload all
+ attributes and collections of all instances touched in the query,
+ including eagerly-loaded entities.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added eagerload_all(), allows eagerload_all('x.y.z') to specify eager
+ loading of all properties in the given path.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Major overhaul for Session:
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ New function which "configures" a session called "sessionmaker()". Send
+ various keyword arguments to this function once, returns a new class
+ which creates a Session against that stereotype.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ SessionTransaction removed from "public" API. You now can call begin()/
+ commit()/rollback() on the Session itself.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session also supports SAVEPOINT transactions; call begin_nested().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session supports two-phase commit behavior when vertically or
+ horizontally partitioning (i.e., using more than one engine). Use
+ twophase=True.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session flag "transactional=True" produces a session which always places
+ itself into a transaction when first used. Upon commit(), rollback() or
+ close(), the transaction ends; but begins again on the next usage.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session supports "autoflush=True". This issues a flush() before each
+ query. Use in conjunction with transactional, and you can just
+ save()/update() and then query, the new objects will be there. Use
+ commit() at the end (or flush() if non-transactional) to flush remaining
+ changes.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ New scoped_session() function replaces SessionContext and assignmapper.
+ Builds onto "sessionmaker()" concept to produce a class whos Session()
+ construction returns the thread-local session. Or, call all Session
+ methods as class methods, i.e. Session.save(foo); Session.commit().
+ just like the old "objectstore" days.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added new "binds" argument to Session to support configuration of
+ multiple binds with sessionmaker() function.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ A rudimental SessionExtension class has been added, allowing
+ user-defined functionality to take place at flush(), commit(), and
+ rollback() boundaries.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query-based relation()s available with dynamic_loader(). This is a
+ *writable* collection (supporting append() and remove()) which is also a
+ live Query object when accessed for reads. Ideal for dealing with very
+ large collections where only partial loading is desired.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ flush()-embedded inline INSERT/UPDATE expressions. Assign any SQL
+ expression, like "sometable.c.column + 1", to an instance's attribute.
+ Upon flush(), the mapper detects the expression and embeds it directly in
+ the INSERT or UPDATE statement; the attribute gets deferred on the
+ instance so it loads the new value the next time you access it.
+
+ .. change::
+ :tags: orm
+ :tickets: 618
+
+ A rudimental sharding (horizontal scaling) system is introduced. This
+ system uses a modified Session which can distribute read and write
+ operations among multiple databases, based on user-defined functions
+ defining the "sharding strategy". Instances and their dependents can be
+ distributed and queried among multiple databases based on attribute
+ values, round-robin approaches or any other user-defined
+ system.
+
+ .. change::
+ :tags: orm
+ :tickets: 659
+
+ Eager loading has been enhanced to allow even more joins in more places.
+ It now functions at any arbitrary depth along self-referential and
+ cyclical structures. When loading cyclical structures, specify
+ "join_depth" on relation() indicating how many times you'd like the table
+ to join to itself; each level gets a distinct table alias. The alias
+ names themselves are generated at compile time using a simple counting
+ scheme now and are a lot easier on the eyes, as well as of course
+ completely deterministic.
+
+ .. change::
+ :tags: orm
+ :tickets: 211
+
+ Added composite column properties. This allows you to create a type which
+ is represented by more than one column, when using the ORM. Objects of
+ the new type are fully functional in query expressions, comparisons,
+ query.get() clauses, etc. and act as though they are regular single-column
+ scalars... except they're not! Use the function composite(cls, *columns)
+ inside of the mapper's "properties" dict, and instances of cls will be
+ created/mapped to a single attribute, comprised of the values correponding
+ to *columns.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Improved support for custom column_property() attributes which feature
+ correlated subqueries, works better with eager loading now.
+
+ .. change::
+ :tags: orm
+ :tickets: 611
+
+ Primary key "collapse" behavior; the mapper will analyze all columns in
+ its given selectable for primary key "equivalence", that is, columns which
+ are equivalent via foreign key relationship or via an explicit
+ inherit_condition. primarily for joined-table inheritance scenarios where
+ different named PK columns in inheriting tables should "collapse" into a
+ single-valued (or fewer-valued) primary key. Fixes things like.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Joined-table inheritance will now generate the primary key columns of all
+ inherited classes against the root table of the join only. This implies
+ that each row in the root table is distinct to a single instance. If for
+ some rare reason this is not desireable, explicit primary_key settings on
+ individual mappers will override it.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ When "polymorphic" flags are used with joined-table or single-table
+ inheritance, all identity keys are generated against the root class of the
+ inheritance hierarchy; this allows query.get() to work polymorphically
+ using the same caching semantics as a non-polymorphic get. Note that this
+ currently does not work with concrete inheritance.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Secondary inheritance loading: polymorphic mappers can be constructed
+ *without* a select_table argument. inheriting mappers whose tables were
+ not represented in the initial load will issue a second SQL query
+ immediately, once per instance (i.e. not very efficient for large lists),
+ in order to load the remaining columns.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Secondary inheritance loading can also move its second query into a
+ column-level "deferred" load, via the "polymorphic_fetch" argument, which
+ can be set to 'select' or 'deferred'
+
+ .. change::
+ :tags: orm
+ :tickets: 696
+
+ It's now possible to map only a subset of available selectable columns
+ onto mapper properties, using include_columns/exclude_columns..
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added undefer_group() MapperOption, sets a set of "deferred" columns
+ joined by a "group" to load as "undeferred".
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Rewrite of the "deterministic alias name" logic to be part of the SQL
+ layer, produces much simpler alias and label names more in the style of
+ Hibernate
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Speed! Clause compilation as well as the mechanics of SQL constructs have
+ been streamlined and simplified to a signficant degree, for a 20-30%
+ improvement of the statement construction/compilation overhead of 0.3.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ All "type" keyword arguments, such as those to bindparam(), column(),
+ Column(), and func.<something>(), renamed to "type_". Those objects still
+ name their "type" attribute as "type".
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ case_sensitive=(True|False) setting removed from schema items, since
+ checking this state added a lot of method call overhead and there was no
+ decent reason to ever set it to False. Table and column names which are
+ all lower case will be treated as case-insenstive (yes we adjust for
+ Oracle's UPPERCASE style too).
+
+ .. change::
+ :tags: transactions
+ :tickets:
+
+ Added context manager (with statement) support for transactions.
+
+ .. change::
+ :tags: transactions
+ :tickets:
+
+ Added support for two phase commit, works with mysql and postgres so far.
+
+ .. change::
+ :tags: transactions
+ :tickets:
+
+ Added a subtransaction implementation that uses savepoints.
+
+ .. change::
+ :tags: transactions
+ :tickets:
+
+ Added support for savepoints.
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ Tables can be reflected from the database en-masse without declaring
+ them in advance. MetaData(engine, reflect=True) will load all tables
+ present in the database, or use metadata.reflect() for finer control.
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ DynamicMetaData has been renamed to ThreadLocalMetaData
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ The ThreadLocalMetaData constructor now takes no arguments.
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ BoundMetaData has been removed- regular MetaData is equivalent
+
+ .. change::
+ :tags: metadata
+ :tickets: 646
+
+ Numeric and Float types now have an "asdecimal" flag; defaults to True for
+ Numeric, False for Float. When True, values are returned as
+ decimal.Decimal objects; when False, values are returned as float(). The
+ defaults of True/False are already the behavior for PG and MySQL's DBAPI
+ modules.
+
+ .. change::
+ :tags: metadata
+ :tickets: 475
+
+ New SQL operator implementation which removes all hardcoded operators from
+ expression structures and moves them into compilation; allows greater
+ flexibility of operator compilation; for example, "+" compiles to "||"
+ when used in a string context, or "concat(a,b)" on MySQL; whereas in a
+ numeric context it compiles to "+". Fixes.
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ "Anonymous" alias and label names are now generated at SQL compilation
+ time in a completely deterministic fashion... no more random hex IDs
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ Significant architectural overhaul to SQL elements (ClauseElement). All
+ elements share a common "mutability" framework which allows a consistent
+ approach to in-place modifications of elements as well as generative
+ behavior. Improves stability of the ORM which makes heavy usage of
+ mutations to SQL expressions.
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ select() and union()'s now have "generative" behavior. Methods like
+ order_by() and group_by() return a *new* instance - the original instance
+ is left unchanged. Non-generative methods remain as well.
+
+ .. change::
+ :tags: metadata
+ :tickets: 569, 52
+
+ The internals of select/union vastly simplified- all decision making
+ regarding "is subquery" and "correlation" pushed to SQL generation phase.
+ select() elements are now *never* mutated by their enclosing containers or
+ by any dialect's compilation process
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ select(scalar=True) argument is deprecated; use select(..).as_scalar().
+ The resulting object obeys the full "column" interface and plays better
+ within expressions.
+
+ .. change::
+ :tags: metadata
+ :tickets: 504
+
+ Added select().with_prefix('foo') allowing any set of keywords to be
+ placed before the columns clause of the SELECT
+
+ .. change::
+ :tags: metadata
+ :tickets: 686
+
+ Added array slice support to row[<index>]
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ Result sets make a better attempt at matching the DBAPI types present in
+ cursor.description to the TypeEngine objects defined by the dialect, which
+ are then used for result-processing. Note this only takes effect for
+ textual SQL; constructed SQL statements always have an explicit type map.
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ Result sets from CRUD operations close their underlying cursor immediately
+ and will also autoclose the connection if defined for the operation; this
+ allows more efficient usage of connections for successive CRUD operations
+ with less chance of "dangling connections".
+
+ .. change::
+ :tags: metadata
+ :tickets: 559
+
+ Column defaults and onupdate Python functions (i.e. passed to
+ ColumnDefault) may take zero or one arguments; the one argument is the
+ ExecutionContext, from which you can call "context.parameters[someparam]"
+ to access the other bind parameter values affixed to the statement. The connection used for the execution is available as well
+ so that you can pre-execute statements.
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ Added "explcit" create/drop/execute support for sequences (i.e. you can
+ pass a "connectable" to each of those methods on Sequence).
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ Better quoting of identifiers when manipulating schemas.
+
+ .. change::
+ :tags: metadata
+ :tickets:
+
+ Standardized the behavior for table reflection where types can't be
+ located; NullType is substituted instead, warning is raised.
+
+ .. change::
+ :tags: metadata
+ :tickets: 606
+
+ ColumnCollection (i.e. the 'c' attribute on tables) follows dictionary
+ semantics for "__contains__"
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Speed! The mechanics of result processing and bind parameter processing
+ have been overhauled, streamlined and optimized to issue as little method
+ calls as possible. Bench tests for mass INSERT and mass rowset iteration
+ both show 0.4 to be over twice as fast as 0.3, using 68% fewer function
+ calls.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ You can now hook into the pool lifecycle and run SQL statements or other
+ logic at new each DBAPI connection, pool check-out and check-in.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Connections gain a .properties collection, with contents scoped to the
+ lifetime of the underlying DBAPI connection
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Removed auto_close_cursors and disallow_open_cursors arguments from Pool;
+ reduces overhead as cursors are normally closed by ResultProxy and
+ Connection.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ proxyengine is temporarily removed, pending an actually working
+ replacement.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ SelectResults has been replaced by Query. SelectResults /
+ SelectResultsExt still exist but just return a slightly modified Query
+ object for backwards-compatibility. join_to() method from SelectResults
+ isn't present anymore, need to use join().
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Table and column names loaded via reflection are now Unicode.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ All standard column types are now supported, including SET.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Table reflection can now be performed in as little as one round-trip.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ ANSI and ANSI_QUOTES sql modes are now supported.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Indexes are now reflected.
+
+ .. change::
+ :tags: postgres
+ :tickets:
+
+ Added PGArray datatype for using postgres array datatypes.
+
+ .. change::
+ :tags: oracle
+ :tickets: 507
+
+ Very rudimental support for OUT parameters added; use sql.outparam(name,
+ type) to set up an OUT parameter, just like bindparam(); after execution,
+ values are avaiable via result.out_parameters dictionary.
--- /dev/null
+
+==============
+0.5 Changelog
+==============
+
+
+.. changelog::
+ :version: 0.5.9
+ :released:
+
+ .. change::
+ :tags: sql
+ :tickets: 1661
+
+ Fixed erroneous self_group() call in expression package.
+
+.. changelog::
+ :version: 0.5.8
+ :released: Sat Jan 16 2010
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The copy() method on Column now supports uninitialized,
+ unnamed Column objects. This allows easy creation of
+ declarative helpers which place common columns on multiple
+ subclasses.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Default generators like Sequence() translate correctly
+ across a copy() operation.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Sequence() and other DefaultGenerator objects are accepted
+ as the value for the "default" and "onupdate" keyword
+ arguments of Column, in addition to being accepted
+ positionally.
+
+ .. change::
+ :tags: sql
+ :tickets: 1568, 1617
+
+ Fixed a column arithmetic bug that affected column
+ correspondence for cloned selectables which contain
+ free-standing column expressions. This bug is
+ generally only noticeable when exercising newer
+ ORM behavior only availble in 0.6 via,
+ but is more correct at the SQL expression level
+ as well.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1647
+
+ The extract() function, which was slightly improved in
+ 0.5.7, needed a lot more work to generate the correct
+ typecast (the typecasts appear to be necessary in PG's
+ EXTRACT quite a lot of the time). The typecast is
+ now generated using a rule dictionary based
+ on PG's documentation for date/time/interval arithmetic.
+ It also accepts text() constructs again, which was broken
+ in 0.5.7.
+
+ .. change::
+ :tags: firebird
+ :tickets: 1646
+
+ Recognize more errors as disconnections.
+
+.. changelog::
+ :version: 0.5.7
+ :released: Sat Dec 26 2009
+
+ .. change::
+ :tags: orm
+ :tickets: 1543
+
+ contains_eager() now works with the automatically
+ generated subquery that results when you say
+ "query(Parent).join(Parent.somejoinedsubclass)", i.e.
+ when Parent joins to a joined-table-inheritance subclass.
+ Previously contains_eager() would erroneously add the
+ subclass table to the query separately producing a
+ cartesian product. An example is in the ticket
+ description.
+
+ .. change::
+ :tags: orm
+ :tickets: 1553
+
+ query.options() now only propagate to loaded objects
+ for potential further sub-loads only for options where
+ such behavior is relevant, keeping
+ various unserializable options like those generated
+ by contains_eager() out of individual instance states.
+
+ .. change::
+ :tags: orm
+ :tickets: 1054
+
+ Session.execute() now locates table- and
+ mapper-specific binds based on a passed
+ in expression which is an insert()/update()/delete()
+ construct.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session.merge() now properly overwrites a many-to-one or
+ uselist=False attribute to None if the attribute
+ is also None in the given object to be merged.
+
+ .. change::
+ :tags: orm
+ :tickets: 1618
+
+ Fixed a needless select which would occur when merging
+ transient objects that contained a null primary key
+ identifier.
+
+ .. change::
+ :tags: orm
+ :tickets: 1585
+
+ Mutable collection passed to the "extension" attribute
+ of relation(), column_property() etc. will not be mutated
+ or shared among multiple instrumentation calls, preventing
+ duplicate extensions, such as backref populators,
+ from being inserted into the list.
+
+ .. change::
+ :tags: orm
+ :tickets: 1504
+
+ Fixed the call to get_committed_value() on CompositeProperty.
+
+ .. change::
+ :tags: orm
+ :tickets: 1602
+
+ Fixed bug where Query would crash if a join() with no clear
+ "left" side were called when a non-mapped column entity
+ appeared in the columns list.
+
+ .. change::
+ :tags: orm
+ :tickets: 1616, 1480
+
+ Fixed bug whereby composite columns wouldn't load properly
+ when configured on a joined-table subclass, introduced in
+ version 0.5.6 as a result of the fix for. thx to Scott Torborg.
+
+ .. change::
+ :tags: orm
+ :tickets: 1556
+
+ The "use get" behavior of many-to-one relations, i.e. that a
+ lazy load will fallback to the possibly cached query.get()
+ value, now works across join conditions where the two compared
+ types are not exactly the same class, but share the same
+ "affinity" - i.e. Integer and SmallInteger. Also allows
+ combinations of reflected and non-reflected types to work
+ with 0.5 style type reflection, such as PGText/Text (note 0.6
+ reflects types as their generic versions).
+
+ .. change::
+ :tags: orm
+ :tickets: 1436
+
+ Fixed bug in query.update() when passing Cls.attribute
+ as keys in the value dict and using synchronize_session='expire'
+ ('fetch' in 0.6).
+
+ .. change::
+ :tags: sql
+ :tickets: 1603
+
+ Fixed bug in two-phase transaction whereby commit() method
+ didn't set the full state which allows subsequent close()
+ call to succeed.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed the "numeric" paramstyle, which apparently is the
+ default paramstyle used by Informixdb.
+
+ .. change::
+ :tags: sql
+ :tickets: 1574
+
+ Repeat expressions in the columns clause of a select
+ are deduped based on the identity of each clause element,
+ not the actual string. This allows positional
+ elements to render correctly even if they all render
+ identically, such as "qmark" style bind parameters.
+
+ .. change::
+ :tags: sql
+ :tickets: 1632
+
+ The cursor associated with connection pool connections
+ (i.e. _CursorFairy) now proxies `__iter__()` to the
+ underlying cursor correctly.
+
+ .. change::
+ :tags: sql
+ :tickets: 1556
+
+ types now support an "affinity comparison" operation, i.e.
+ that an Integer/SmallInteger are "compatible", or
+ a Text/String, PickleType/Binary, etc. Part of.
+
+ .. change::
+ :tags: sql
+ :tickets: 1641
+
+ Fixed bug preventing alias() of an alias() from being
+ cloned or adapted (occurs frequently in ORM operations).
+
+ .. change::
+ :tags: sqlite
+ :tickets: 1439
+
+ sqlite dialect properly generates CREATE INDEX for a table
+ that is in an alternate schema.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1085
+
+ Added support for reflecting the DOUBLE PRECISION type,
+ via a new postgres.PGDoublePrecision object.
+ This is postgresql.DOUBLE_PRECISION in 0.6.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 460
+
+ Added support for reflecting the INTERVAL YEAR TO MONTH
+ and INTERVAL DAY TO SECOND syntaxes of the INTERVAL
+ type.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1576
+
+ Corrected the "has_sequence" query to take current schema,
+ or explicit sequence-stated schema, into account.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1611
+
+ Fixed the behavior of extract() to apply operator
+ precedence rules to the "::" operator when applying
+ the "timestamp" cast - ensures proper parenthesization.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1561
+
+ Changed the name of TrustedConnection to
+ Trusted_Connection when constructing pyodbc connect
+ arguments
+
+ .. change::
+ :tags: oracle
+ :tickets: 1637
+
+ The "table_names" dialect function, used by MetaData
+ .reflect(), omits "index overflow tables", a system
+ table generated by Oracle when "index only tables"
+ with overflow are used. These tables aren't accessible
+ via SQL and can't be reflected.
+
+ .. change::
+ :tags: ext
+ :tickets: 1570, 1523
+
+ A column can be added to a joined-table declarative
+ superclass after the class has been constructed
+ (i.e. via class-level attribute assignment), and
+ the column will be propagated down to
+ subclasses. This is the reverse
+ situation as that of, fixed in 0.5.6.
+
+ .. change::
+ :tags: ext
+ :tickets: 1491
+
+ Fixed a slight inaccuracy in the sharding example.
+ Comparing equivalence of columns in the ORM is best
+ accomplished using col1.shares_lineage(col2).
+
+ .. change::
+ :tags: ext
+ :tickets: 1606
+
+ Removed unused `load()` method from ShardedQuery.
+
+.. changelog::
+ :version: 0.5.6
+ :released: Sat Sep 12 2009
+
+ .. change::
+ :tags: orm
+ :tickets: 1300
+
+ Fixed bug whereby inheritance discriminator part of a
+ composite primary key would fail on updates.
+ Continuation of.
+
+ .. change::
+ :tags: orm
+ :tickets: 1507
+
+ Fixed bug which disallowed one side of a many-to-many
+ bidirectional reference to declare itself as "viewonly"
+
+ .. change::
+ :tags: orm
+ :tickets: 1526
+
+ Added an assertion that prevents a @validates function
+ or other AttributeExtension from loading an unloaded
+ collection such that internal state may be corrupted.
+
+ .. change::
+ :tags: orm
+ :tickets: 1519
+
+ Fixed bug which prevented two entities from mutually
+ replacing each other's primary key values within a single
+ flush() for some orderings of operations.
+
+ .. change::
+ :tags: orm
+ :tickets: 1485
+
+ Fixed an obscure issue whereby a joined-table subclass
+ with a self-referential eager load on the base class
+ would populate the related object's "subclass" table with
+ data from the "subclass" table of the parent.
+
+ .. change::
+ :tags: orm
+ :tickets: 1477
+
+ relations() now have greater ability to be "overridden",
+ meaning a subclass that explicitly specifies a relation()
+ overriding that of the parent class will be honored
+ during a flush. This is currently to support
+ many-to-many relations from concrete inheritance setups.
+ Outside of that use case, YMMV.
+
+ .. change::
+ :tags: orm
+ :tickets: 1483
+
+ Squeezed a few more unnecessary "lazy loads" out of
+ relation(). When a collection is mutated, many-to-one
+ backrefs on the other side will not fire off to load
+ the "old" value, unless "single_parent=True" is set.
+ A direct assignment of a many-to-one still loads
+ the "old" value in order to update backref collections
+ on that value, which may be present in the session
+ already, thus maintaining the 0.5 behavioral contract.
+
+ .. change::
+ :tags: orm
+ :tickets: 1480
+
+ Fixed bug whereby a load/refresh of joined table
+ inheritance attributes which were based on
+ column_property() or similar would fail to evaluate.
+
+ .. change::
+ :tags: orm
+ :tickets: 1488
+
+ Improved support for MapperProperty objects overriding
+ that of an inherited mapper for non-concrete
+ inheritance setups - attribute extensions won't randomly
+ collide with each other.
+
+ .. change::
+ :tags: orm
+ :tickets: 1487
+
+ UPDATE and DELETE do not support ORDER BY, LIMIT, OFFSET,
+ etc. in standard SQL. Query.update() and Query.delete()
+ now raise an exception if any of limit(), offset(),
+ order_by(), group_by(), or distinct() have been
+ called.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added AttributeExtension to sqlalchemy.orm.__all__
+
+ .. change::
+ :tags: orm
+ :tickets: 1476
+
+ Improved error message when query() is called with
+ a non-SQL /entity expression.
+
+ .. change::
+ :tags: orm
+ :tickets: 1440
+
+ Using False or 0 as a polymorphic discriminator now
+ works on the base class as well as a subclass.
+
+ .. change::
+ :tags: orm
+ :tickets: 1424
+
+ Added enable_assertions(False) to Query which disables
+ the usual assertions for expected state - used
+ by Query subclasses to engineer custom state.. See
+ http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery
+ for an example.
+
+ .. change::
+ :tags: orm
+ :tickets: 1501
+
+ Fixed recursion issue which occured if a mapped object's
+ `__len__()` or `__nonzero__()` method resulted in state
+ changes.
+
+ .. change::
+ :tags: orm
+ :tickets: 1506
+
+ Fixed incorrect exception raise in
+ Weak/StrongIdentityMap.add()
+
+ .. change::
+ :tags: orm
+ :tickets: 1522
+
+ Fixed the error message for "could not find a FROM clause"
+ in query.join() which would fail to issue correctly
+ if the query was against a pure SQL construct.
+
+ .. change::
+ :tags: orm
+ :tickets: 1486
+
+ Fixed a somewhat hypothetical issue which would result
+ in the wrong primary key being calculated for a mapper
+ using the old polymorphic_union function - but this
+ is old stuff.
+
+ .. change::
+ :tags: sql
+ :tickets: 1373
+
+ Fixed column.copy() to copy defaults and onupdates.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed a bug in extract() introduced in 0.5.4 whereby
+ the string "field" argument was getting treated as a
+ ClauseElement, causing various errors within more
+ complex SQL transformations.
+
+ .. change::
+ :tags: sql
+ :tickets: 1420
+
+ Unary expressions such as DISTINCT propagate their
+ type handling to result sets, allowing conversions like
+ unicode and such to take place.
+
+ .. change::
+ :tags: sql
+ :tickets: 1482
+
+ Fixed bug in Table and Column whereby passing empty
+ dict for "info" argument would raise an exception.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1309
+
+ Backported 0.6 fix for Oracle alias names not getting
+ truncated.
+
+ .. change::
+ :tags: ext
+ :tickets: 1446
+
+ The collection proxies produced by associationproxy are now
+ pickleable. A user-defined proxy_factory however
+ is still not pickleable unless it defines __getstate__
+ and __setstate__.
+
+ .. change::
+ :tags: ext
+ :tickets: 1468
+
+ Declarative will raise an informative exception if
+ __table_args__ is passed as a tuple with no dict argument.
+ Improved documentation.
+
+ .. change::
+ :tags: ext
+ :tickets: 1527
+
+ Table objects declared in the MetaData can now be used
+ in string expressions sent to primaryjoin/secondaryjoin/
+ secondary - the name is pulled from the MetaData of the
+ declarative base.
+
+ .. change::
+ :tags: ext
+ :tickets: 1523
+
+ A column can be added to a joined-table subclass after
+ the class has been constructed (i.e. via class-level
+ attribute assignment). The column is added to the underlying
+ Table as always, but now the mapper will rebuild its
+ "join" to include the new column, instead of raising
+ an error about "no such column, use column_property()
+ instead".
+
+ .. change::
+ :tags: test
+ :tickets:
+
+ Added examples into the test suite so they get exercised
+ regularly and cleaned up a couple deprecation warnings.
+
+.. changelog::
+ :version: 0.5.5
+ :released: Mon Jul 13 2009
+
+ .. change::
+ :tags: general
+ :tickets: 970
+
+ unit tests have been migrated from unittest to nose. See
+ README.unittests for information on how to run the tests.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The "foreign_keys" argument of relation() will now propagate
+ automatically to the backref in the same way that primaryjoin
+ and secondaryjoin do. For the extremely rare use case where
+ the backref of a relation() has intentionally different
+ "foreign_keys" configured, both sides now need to be
+ configured explicity (if they do in fact require this setting,
+ see the next note...).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ ...the only known (and really, really rare) use case where a
+ different foreign_keys setting was used on the
+ forwards/backwards side, a composite foreign key that
+ partially points to its own columns, has been enhanced such
+ that the fk->itself aspect of the relation won't be used to
+ determine relation direction.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session.mapper is now *deprecated*.
+
+ Call session.add() if you'd like a free-standing object to be
+ part of your session. Otherwise, a DIY version of
+ Session.mapper is now documented at
+ http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper
+ The method will remain deprecated throughout 0.6.
+
+ .. change::
+ :tags: orm
+ :tickets: 1431
+
+ Fixed Query being able to join() from individual columns of a
+ joined-table subclass entity, i.e. query(SubClass.foo,
+ SubcClass.bar).join(<anything>). In most cases, an error
+ "Could not find a FROM clause to join from" would be
+ raised. In a few others, the result would be returned in terms
+ of the base class rather than the subclass - so applications
+ which relied on this erroneous result need to be
+ adjusted.
+
+ .. change::
+ :tags: orm
+ :tickets: 1461
+
+ Fixed a bug involving contains_eager(), which would apply
+ itself to a secondary (i.e. lazy) load in a particular rare
+ case, producing cartesian products. improved the targeting of
+ query.options() on secondary loads overall.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug introduced in 0.5.4 whereby Composite types fail
+ when default-holding columns are flushed.
+
+ .. change::
+ :tags: orm
+ :tickets: 1426
+
+ Fixed another 0.5.4 bug whereby mutable attributes
+ (i.e. PickleType) wouldn't be deserialized correctly when the
+ whole object was serialized.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug whereby session.is_modified() would raise an
+ exception if any synonyms were in use.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed potential memory leak whereby previously pickled objects
+ placed back in a session would not be fully garbage collected
+ unless the Session were explicitly closed out.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug whereby list-based attributes, like pickletype and
+ PGArray, failed to be merged() properly.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Repaired non-working attributes.set_committed_value function.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Trimmed the pickle format for InstanceState which should
+ further reduce the memory footprint of pickled instances. The
+ format should be backwards compatible with that of 0.5.4 and
+ previous.
+
+ .. change::
+ :tags: orm
+ :tickets: 1463
+
+ sqlalchemy.orm.join and sqlalchemy.orm.outerjoin are now
+ added to __all__ in sqlalchemy.orm.*.
+
+ .. change::
+ :tags: orm
+ :tickets: 1458
+
+ Fixed bug where Query exception raise would fail when
+ a too-short composite primary key value were passed to
+ get().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Removed an obscure feature of execute() (including connection,
+ engine, Session) whereby a bindparam() construct can be sent
+ as a key to the params dictionary. This usage is undocumented
+ and is at the core of an issue whereby the bindparam() object
+ created implicitly by a text() construct may have the same
+ hash value as a string placed in the params dictionary and may
+ result in an inappropriate match when computing the final bind
+ parameters. Internal checks for this condition would add
+ significant latency to the critical task of parameter
+ rendering, so the behavior is removed. This is a backwards
+ incompatible change for any application that may have been
+ using this feature, however the feature has never been
+ documented.
+
+ .. change::
+ :tags: engine/pool
+ :tickets:
+
+ Implemented recreate() for StaticPool.
+
+.. changelog::
+ :version: 0.5.4p2
+ :released: Tue May 26 2009
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Repaired the printing of SQL exceptions which are not
+ based on parameters or are not executemany() style.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ Deprecated the hardcoded TIMESTAMP function, which when
+ used as func.TIMESTAMP(value) would render "TIMESTAMP value".
+ This breaks on some platforms as PostgreSQL doesn't allow
+ bind parameters to be used in this context. The hard-coded
+ uppercase is also inappropriate and there's lots of other
+ PG casts that we'd need to support. So instead, use
+ text constructs i.e. select(["timestamp '12/05/09'"]).
+
+.. changelog::
+ :version: 0.5.4p1
+ :released: Mon May 18 2009
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed an attribute error introduced in 0.5.4 which would
+ occur when merge() was used with an incomplete object.
+
+.. changelog::
+ :version: 0.5.4
+ :released: Sun May 17 2009
+
+ .. change::
+ :tags: orm
+ :tickets: 1398
+
+ Significant performance enhancements regarding Sessions/flush()
+ in conjunction with large mapper graphs, large numbers of
+ objects:
+
+ - Removed all* O(N) scanning behavior from the flush() process,
+ i.e. operations that were scanning the full session,
+ including an extremely expensive one that was erroneously
+ assuming primary key values were changing when this
+ was not the case.
+
+ * one edge case remains which may invoke a full scan,
+ if an existing primary key attribute is modified
+ to a new value.
+
+ - The Session's "weak referencing" behavior is now *full* -
+ no strong references whatsoever are made to a mapped object
+ or related items/collections in its __dict__. Backrefs and
+ other cycles in objects no longer affect the Session's ability
+ to lose all references to unmodified objects. Objects with
+ pending changes still are maintained strongly until flush.
+
+
+ The implementation also improves performance by moving
+ the "resurrection" process of garbage collected items
+ to only be relevant for mappings that map "mutable"
+ attributes (i.e. PickleType, composite attrs). This removes
+ overhead from the gc process and simplifies internal
+ behavior.
+
+ If a "mutable" attribute change is the sole change on an object
+ which is then dereferenced, the mapper will not have access to
+ other attribute state when the UPDATE is issued. This may present
+ itself differently to some MapperExtensions.
+
+ The change also affects the internal attribute API, but not
+ the AttributeExtension interface nor any of the publically
+ documented attribute functions.
+
+ - The unit of work no longer genererates a graph of "dependency"
+ processors for the full graph of mappers during flush(), instead
+ creating such processors only for those mappers which represent
+ objects with pending changes. This saves a tremendous number
+ of method calls in the context of a large interconnected
+ graph of mappers.
+
+ - Cached a wasteful "table sort" operation that previously
+ occured multiple times per flush, also removing significant
+ method call count from flush().
+
+ - Other redundant behaviors have been simplified in
+ mapper._save_obj().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Modified query_cls on DynamicAttributeImpl to accept a full
+ mixin version of the AppenderQuery, which allows subclassing
+ the AppenderMixin.
+
+ .. change::
+ :tags: orm
+ :tickets: 1300
+
+ The "polymorphic discriminator" column may be part of a
+ primary key, and it will be populated with the correct
+ discriminator value.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed the evaluator not being able to evaluate IS NULL clauses.
+
+ .. change::
+ :tags: orm
+ :tickets: 1352
+
+ Fixed the "set collection" function on "dynamic" relations to
+ initiate events correctly. Previously a collection could only
+ be assigned to a pending parent instance, otherwise modified
+ events would not be fired correctly. Set collection is now
+ compatible with merge(), fixes.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Allowed pickling of PropertyOption objects constructed with
+ instrumented descriptors; previously, pickle errors would occur
+ when pickling an object which was loaded with a descriptor-based
+ option, such as query.options(eagerload(MyClass.foo)).
+
+ .. change::
+ :tags: orm
+ :tickets: 1357
+
+ Lazy loader will not use get() if the "lazy load" SQL clause
+ matches the clause used by get(), but contains some parameters
+ hardcoded. Previously the lazy strategy would fail with the
+ get(). Ideally get() would be used with the hardcoded
+ parameters but this would require further development.
+
+ .. change::
+ :tags: orm
+ :tickets: 1391
+
+ MapperOptions and other state associated with query.options()
+ is no longer bundled within callables associated with each
+ lazy/deferred-loading attribute during a load.
+ The options are now associated with the instance's
+ state object just once when it's populated. This removes
+ the need in most cases for per-instance/attribute loader
+ objects, improving load speed and memory overhead for
+ individual instances.
+
+ .. change::
+ :tags: orm
+ :tickets: 1360
+
+ Fixed another location where autoflush was interfering
+ with session.merge(). autoflush is disabled completely
+ for the duration of merge() now.
+
+ .. change::
+ :tags: orm
+ :tickets: 1406
+
+ Fixed bug which prevented "mutable primary key" dependency
+ logic from functioning properly on a one-to-one
+ relation().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug in relation(), introduced in 0.5.3,
+ whereby a self referential relation
+ from a base class to a joined-table subclass would
+ not configure correctly.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed obscure mapper compilation issue when inheriting
+ mappers are used which would result in un-initialized
+ attributes.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed documentation for session weak_identity_map -
+ the default value is True, indicating a weak
+ referencing map in use.
+
+ .. change::
+ :tags: orm
+ :tickets: 1376
+
+ Fixed a unit of work issue whereby the foreign
+ key attribute on an item contained within a collection
+ owned by an object being deleted would not be set to
+ None if the relation() was self-referential.
+
+ .. change::
+ :tags: orm
+ :tickets: 1378
+
+ Fixed Query.update() and Query.delete() failures with eagerloaded
+ relations.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ It is now an error to specify both columns of a binary primaryjoin
+ condition in the foreign_keys or remote_side collection. Whereas
+ previously it was just nonsensical, but would succeed in a
+ non-deterministic way.
+
+ .. change::
+ :tags: ticket: 594, 1341, schema
+ :tickets:
+
+ Added a quote_schema() method to the IdentifierPreparer class
+ so that dialects can override how schemas get handled. This
+ enables the MSSQL dialect to treat schemas as multipart
+ identifiers, such as 'database.owner'.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Back-ported the "compiler" extension from SQLA 0.6. This
+ is a standardized interface which allows the creation of custom
+ ClauseElement subclasses and compilers. In particular it's
+ handy as an alternative to text() when you'd like to
+ build a construct that has database-specific compilations.
+ See the extension docs for details.
+
+ .. change::
+ :tags: sql
+ :tickets: 1413
+
+ Exception messages are truncated when the list of bound
+ parameters is larger than 10, preventing enormous
+ multi-page exceptions from filling up screens and logfiles
+ for large executemany() statements.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ ``sqlalchemy.extract()`` is now dialect sensitive and can
+ extract components of timestamps idiomatically across the
+ supported databases, including SQLite.
+
+ .. change::
+ :tags: sql
+ :tickets: 1353
+
+ Fixed __repr__() and other _get_colspec() methods on
+ ForeignKey constructed from __clause_element__() style
+ construct (i.e. declarative columns).
+
+ .. change::
+ :tags: mysql
+ :tickets: 1405
+
+ Reflecting a FOREIGN KEY construct will take into account
+ a dotted schema.tablename combination, if the foreign key
+ references a table in a remote schema.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Modified how savepoint logic works to prevent it from
+ stepping on non-savepoint oriented routines. Savepoint
+ support is still very experimental.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1310
+
+ Added in reserved words for MSSQL that covers version 2008
+ and all prior versions.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1343
+
+ Corrected problem with information schema not working with a
+ binary collation based database. Cleaned up information schema
+ since it is only used by mssql now.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 1402
+
+ Corrected the SLBoolean type so that it properly treats only 1
+ as True.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 1273
+
+ Corrected the float type so that it correctly maps to a
+ SLFloat type when being reflected.
+
+ .. change::
+ :tags: extensions
+ :tickets: 1379
+
+ Fixed adding of deferred or other column properties to a
+ declarative class.
+
+.. changelog::
+ :version: 0.5.3
+ :released: Tue Mar 24 2009
+
+ .. change::
+ :tags: orm
+ :tickets: 1315
+
+ The "objects" argument to session.flush() is deprecated.
+ State which represents the linkage between a parent and
+ child object does not support "flushed" status on
+ one side of the link and not the other, so supporting
+ this operation leads to misleading results.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query now implements __clause_element__() which produces
+ its selectable, which means a Query instance can be accepted
+ in many SQL expressions, including col.in_(query),
+ union(query1, query2), select([foo]).select_from(query),
+ etc.
+
+ .. change::
+ :tags: orm
+ :tickets: 1337
+
+ Query.join() can now construct multiple FROM clauses, if
+ needed. Such as, query(A, B).join(A.x).join(B.y)
+ might say SELECT A.*, B.* FROM A JOIN X, B JOIN Y.
+ Eager loading can also tack its joins onto those
+ multiple FROM clauses.
+
+ .. change::
+ :tags: orm
+ :tickets: 1347
+
+ Fixed bug in dynamic_loader() where append/remove events
+ after construction time were not being propagated to the
+ UOW to pick up on flush().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug where column_prefix wasn't being checked before
+ not mapping an attribute that already had class-level
+ name present.
+
+ .. change::
+ :tags: orm
+ :tickets: 1315
+
+ a session.expire() on a particular collection attribute
+ will clear any pending backref additions as well, so that
+ the next access correctly returns only what was present
+ in the database. Presents some degree of a workaround for, although we are considering removing the
+ flush([objects]) feature altogether.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session.scalar() now converts raw SQL strings to text()
+ the same way Session.execute() does and accepts same
+ alternative **kw args.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ improvements to the "determine direction" logic of
+ relation() such that the direction of tricky situations
+ like mapper(A.join(B)) -> relation-> mapper(B) can be
+ determined.
+
+ .. change::
+ :tags: orm
+ :tickets: 1306
+
+ When flushing partial sets of objects using session.flush([somelist]),
+ pending objects which remain pending after the operation won't
+ inadvertently be added as persistent.
+
+ .. change::
+ :tags: orm
+ :tickets: 1314
+
+ Added "post_configure_attribute" method to InstrumentationManager,
+ so that the "listen_for_events.py" example works again.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ a forward and complementing backwards reference which are both
+ of the same direction, i.e. ONETOMANY or MANYTOONE,
+ is now detected, and an error message is raised.
+ Saves crazy CircularDependencyErrors later on.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bugs in Query regarding simultaneous selection of
+ multiple joined-table inheritance entities with common base
+ classes:
+
+ - previously the adaption applied to "B" on
+ "A JOIN B" would be erroneously partially applied
+ to "A".
+
+ - comparisons on relations (i.e. A.related==someb)
+ were not getting adapted when they should.
+
+ - Other filterings, like
+ query(A).join(A.bs).filter(B.foo=='bar'), were erroneously
+ adapting "B.foo" as though it were an "A".
+
+ .. change::
+ :tags: orm
+ :tickets: 1325
+
+ Fixed adaptation of EXISTS clauses via any(), has(), etc.
+ in conjunction with an aliased object on the left and
+ of_type() on the right.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added an attribute helper method ``set_committed_value`` in
+ sqlalchemy.orm.attributes. Given an object, attribute name,
+ and value, will set the value on the object as part of its
+ "committed" state, i.e. state that is understood to have
+ been loaded from the database. Helps with the creation of
+ homegrown collection loaders and such.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query won't fail with weakref error when a non-mapper/class
+ instrumented descriptor is passed, raises
+ "Invalid column expession".
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.group_by() properly takes into account aliasing applied
+ to the FROM clause, such as with select_from(), using
+ with_polymorphic(), or using from_self().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ An alias() of a select() will convert to a "scalar subquery"
+ when used in an unambiguously scalar context, i.e. it's used
+ in a comparison operation. This applies to
+ the ORM when using query.subquery() as well.
+
+ .. change::
+ :tags: sql
+ :tickets: 1302
+
+ Fixed missing _label attribute on Function object, others
+ when used in a select() with use_labels (such as when used
+ in an ORM column_property()).
+
+ .. change::
+ :tags: sql
+ :tickets: 1309
+
+ anonymous alias names now truncate down to the max length
+ allowed by the dialect. More significant on DBs like
+ Oracle with very small character limits.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the __selectable__() interface has been replaced entirely
+ by __clause_element__().
+
+ .. change::
+ :tags: sql
+ :tickets: 1299
+
+ The per-dialect cache used by TypeEngine to cache
+ dialect-specific types is now a WeakKeyDictionary.
+ This to prevent dialect objects from
+ being referenced forever for an application that
+ creates an arbitrarily large number of engines
+ or dialects. There is a small performance penalty
+ which will be resolved in 0.6.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ Fixed SQLite reflection methods so that non-present
+ cursor.description, which triggers an auto-cursor
+ close, will be detected so that no results doesn't
+ fail on recent versions of pysqlite which raise
+ an error when fetchone() called with no rows present.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ Index reflection won't fail when an index with
+ multiple expressions is encountered.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1327
+
+ Added PGUuid and PGBit types to
+ sqlalchemy.databases.postgres.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1327
+
+ Refection of unknown PG types won't crash when those
+ types are specified within a domain.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Preliminary support for pymssql 1.0.1
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Corrected issue on mssql where max_identifier_length was
+ not being respected.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ Fixed a recursive pickling issue in serializer, triggered
+ by an EXISTS or other embedded FROM construct.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ Declarative locates the "inherits" class using a search
+ through __bases__, to skip over mixins that are local
+ to subclasses.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ Declarative figures out joined-table inheritance primary join
+ condition even if "inherits" mapper argument is given
+ explicitly.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ Declarative will properly interpret the "foreign_keys" argument
+ on a backref() if it's a string.
+
+ .. change::
+ :tags: extensions
+ :tickets:
+
+ Declarative will accept a table-bound column as a property
+ when used in conjunction with __table__, if the column is already
+ present in __table__. The column will be remapped to the given
+ key the same way as when added to the mapper() properties dict.
+
+.. changelog::
+ :version: 0.5.2
+ :released: Sat Jan 24 2009
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Further refined 0.5.1's warning about delete-orphan cascade
+ placed on a many-to-many relation. First, the bad news:
+ the warning will apply to both many-to-many as well as
+ many-to-one relations. This is necessary since in both
+ cases, SQLA does not scan the full set of potential parents
+ when determining "orphan" status - for a persistent object
+ it only detects an in-python de-association event to establish
+ the object as an "orphan". Next, the good news: to support
+ one-to-one via a foreign key or assocation table, or to
+ support one-to-many via an association table, a new flag
+ single_parent=True may be set which indicates objects
+ linked to the relation are only meant to have a single parent.
+ The relation will raise an error if multiple parent-association
+ events occur within Python.
+
+ .. change::
+ :tags: orm
+ :tickets: 1292
+
+ Adjusted the attribute instrumentation change from 0.5.1 to
+ fully establish instrumentation for subclasses where the mapper
+ was created after the superclass had already been fully
+ instrumented.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug in delete-orphan cascade whereby two one-to-one
+ relations from two different parent classes to the same target
+ class would prematurely expunge the instance.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed an eager loading bug whereby self-referential eager
+ loading would prevent other eager loads, self referential or not,
+ from joining to the parent JOIN properly. Thanks to Alex K
+ for creating a great test case.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ session.expire() and related methods will not expire() unloaded
+ deferred attributes. This prevents them from being needlessly
+ loaded when the instance is refreshed.
+
+ .. change::
+ :tags: orm
+ :tickets: 1293
+
+ query.join()/outerjoin() will now properly join an aliased()
+ construct to the existing left side, even if query.from_self()
+ or query.select_from(someselectable) has been called.
+
+ .. change::
+ :tags: sql
+ :tickets: 1284
+
+ Further fixes to the "percent signs and spaces in column/table
+ names" functionality.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1291
+
+ Restored convert_unicode handling. Results were being passed
+ on through without conversion.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1282
+
+ Really fixing the decimal handling this time..
+
+ .. change::
+ :tags: Ticket:1289, mssql
+ :tickets:
+
+ Modified table reflection code to use only kwargs when
+ constructing tables.
+
+.. changelog::
+ :version: 0.5.1
+ :released: Sat Jan 17 2009
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Removed an internal join cache which could potentially leak
+ memory when issuing query.join() repeatedly to ad-hoc
+ selectables.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The "clear()", "save()", "update()", "save_or_update()"
+ Session methods have been deprecated, replaced by
+ "expunge_all()" and "add()". "expunge_all()" has also
+ been added to ScopedSession.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Modernized the "no mapped table" exception and added a more
+ explicit __table__/__tablename__ exception to declarative.
+
+ .. change::
+ :tags: orm
+ :tickets: 1237
+
+ Concrete inheriting mappers now instrument attributes which
+ are inherited from the superclass, but are not defined for
+ the concrete mapper itself, with an InstrumentedAttribute that
+ issues a descriptive error when accessed.
+
+ .. change::
+ :tags: orm
+ :tickets: 1237, 781
+
+ Added a new `relation()` keyword `back_populates`. This
+ allows configuation of backreferences using explicit
+ relations. This is required when creating
+ bidirectional relations between a hierarchy of concrete
+ mappers and another class.
+
+ .. change::
+ :tags: orm
+ :tickets: 1237
+
+ Test coverage added for `relation()` objects specified on
+ concrete mappers.
+
+ .. change::
+ :tags: orm
+ :tickets: 1276
+
+ Query.from_self() as well as query.subquery() both disable
+ the rendering of eager joins inside the subquery produced.
+ The "disable all eager joins" feature is available publically
+ via a new query.enable_eagerloads() generative.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added a rudimental series of set operations to Query that
+ receive Query objects as arguments, including union(),
+ union_all(), intersect(), except_(), insertsect_all(),
+ except_all(). See the API documentation for
+ Query.union() for examples.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug that prevented Query.join() and eagerloads from
+ attaching to a query that selected from a union or aliased union.
+
+ .. change::
+ :tags: orm
+ :tickets: 1237
+
+ A short documentation example added for bidirectional
+ relations specified on concrete mappers.
+
+ .. change::
+ :tags: orm
+ :tickets: 1269
+
+ Mappers now instrument class attributes upon construction
+ with the final InstrumentedAttribute object which remains
+ persistent. The `_CompileOnAttr`/`__getattribute__()`
+ methodology has been removed. The net effect is that
+ Column-based mapped class attributes can now be used fully
+ at the class level without invoking a mapper compilation
+ operation, greatly simplifying typical usage patterns
+ within declarative.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ ColumnProperty (and front-end helpers such as ``deferred``) no
+ longer ignores unknown **keyword arguments.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed a bug with the unitofwork's "row switch" mechanism,
+ i.e. the conversion of INSERT/DELETE into an UPDATE, when
+ combined with joined-table inheritance and an object
+ which contained no defined values for the child table where
+ an UPDATE with no SET clause would be rendered.
+
+ .. change::
+ :tags: orm
+ :tickets: 1281
+
+ Using delete-orphan on a many-to-many relation is deprecated.
+ This produces misleading or erroneous results since SQLA does
+ not retrieve the full list of "parents" for m2m. To get delete-orphan
+ behavior with an m2m table, use an explcit association class
+ so that the individual association row is treated as a parent.
+
+ .. change::
+ :tags: orm
+ :tickets: 1281
+
+ delete-orphan cascade always requires delete cascade. Specifying
+ delete-orphan without delete now raises a deprecation warning.
+
+ .. change::
+ :tags: sql
+ :tickets: 1256
+
+ Improved the methodology to handling percent signs in column
+ names from. Added more tests. MySQL and
+ PostgreSQL dialects still do not issue correct CREATE TABLE
+ statements for identifiers with percent signs in them.
+
+ .. change::
+ :tags: schema
+ :tickets: 1214
+
+ Index now accepts column-oriented InstrumentedAttributes
+ (i.e. column-based mapped class attributes) as column
+ arguments.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Column with no name (as in declarative) won't raise a
+ NoneType error when it's string output is requsted
+ (such as in a stack trace).
+
+ .. change::
+ :tags: schema
+ :tickets: 1278
+
+ Fixed bug when overriding a Column with a ForeignKey
+ on a reflected table, where derived columns (i.e. the
+ "virtual" columns of a select, etc.) would inadvertently
+ call upon schema-level cleanup logic intended only
+ for the original column.
+
+ .. change::
+ :tags: declarative
+ :tickets:
+
+ Can now specify Column objects on subclasses which have no
+ table of their own (i.e. use single table inheritance).
+ The columns will be appended to the base table, but only
+ mapped by the subclass.
+
+ .. change::
+ :tags: declarative
+ :tickets:
+
+ For both joined and single inheriting subclasses, the subclass
+ will only map those columns which are already mapped on the
+ superclass and those explicit on the subclass. Other
+ columns that are present on the `Table` will be excluded
+ from the mapping by default, which can be disabled
+ by passing a blank `exclude_properties` collection to the
+ `__mapper_args__`. This is so that single-inheriting
+ classes which define their own columns are the only classes
+ to map those columns. The effect is actually a more organized
+ mapping than you'd normally get with explicit `mapper()`
+ calls unless you set up the `exclude_properties` arguments
+ explicitly.
+
+ .. change::
+ :tags: declarative
+ :tickets:
+
+ It's an error to add new Column objects to a declarative class
+ that specified an existing table using __table__.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Added the missing keywords from MySQL 4.1 so they get escaped
+ properly.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1280
+
+ Corrected handling of large decimal values with more robust
+ tests. Removed string manipulation on floats.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Modified the do_begin handling in mssql to use the Cursor not
+ the Connection so it is DBAPI compatible.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Corrected SAVEPOINT support on adodbapi by changing the
+ handling of savepoint_release, which is unsupported on mssql.
+
+.. changelog::
+ :version: 0.5.0
+ :released: Tue Jan 06 2009
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ Documentation has been converted to Sphinx. In particular,
+ the generated API documentation has been constructed into a
+ full blown "API Reference" section which organizes editorial
+ documentation combined with generated docstrings. Cross
+ linking between sections and API docs are vastly improved, a
+ javascript-powered search feature is provided, and a full
+ index of all classes, functions and members is provided.
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ setup.py now imports setuptools only optionally. If not
+ present, distutils is used. The new "pip" installer is
+ recommended over easy_install as it installs in a more
+ simplified way.
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ added an extremely basic illustration of a PostGIS integration
+ to the examples folder.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.with_polymorphic() now accepts a third argument
+ "discriminator" which will replace the value of
+ mapper.polymorphic_on for that query. Mappers themselves no
+ longer require polymorphic_on to be set, even if the mapper
+ has a polymorphic_identity. When not set, the mapper will
+ load non-polymorphically by default. Together, these two
+ features allow a non-polymorphic concrete inheritance setup to
+ use polymorphic loading on a per-query basis, since concrete
+ setups are prone to many issues when used polymorphically in
+ all cases.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ dynamic_loader accepts a query_class= to customize the Query
+ classes used for both the dynamic collection and the queries
+ built from it.
+
+ .. change::
+ :tags: orm
+ :tickets: 1079
+
+ query.order_by() accepts None which will remove any pending
+ order_by state from the query, as well as cancel out any
+ mapper/relation configured ordering. This is primarily useful
+ for overriding the ordering specified on a dynamic_loader().
+
+ .. change::
+ :tags: sql
+ :tickets: 935
+
+ RowProxy objects can be used in place of dictionary arguments
+ sent to connection.execute() and friends.
+
+ .. change::
+ :tags: dialect
+ :tickets:
+
+ Added a new description_encoding attribute on the dialect that
+ is used for encoding the column name when processing the
+ metadata. This usually defaults to utf-8.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Added in a new MSGenericBinary type. This maps to the Binary
+ type so it can implement the specialized behavior of treating
+ length specified types as fixed-width Binary types and
+ non-length types as an unbound variable length Binary type.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1249
+
+ Added in new types: MSVarBinary and MSImage.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Added in the MSReal, MSNText, MSSmallDateTime, MSTime,
+ MSDateTimeOffset, and MSDateTime2 types
+
+ .. change::
+ :tags: sqlite
+ :tickets: 1266
+
+ Table reflection now stores the actual DefaultClause value for
+ the column.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ bugfixes, behavioral changes
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Exceptions raised during compile_mappers() are now preserved
+ to provide "sticky behavior" - if a hasattr() call on a
+ pre-compiled mapped attribute triggers a failing compile and
+ suppresses the exception, subsequent compilation is blocked
+ and the exception will be reiterated on the next compile()
+ call. This issue occurs frequently when using declarative.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ property.of_type() is now recognized on a single-table
+ inheriting target, when used in the context of
+ prop.of_type(..).any()/has(), as well as
+ query.join(prop.of_type(...)).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.join() raises an error when the target of the join
+ doesn't match the property-based attribute - while it's
+ unlikely anyone is doing this, the SQLAlchemy author was
+ guilty of this particular loosey-goosey behavior.
+
+ .. change::
+ :tags: orm
+ :tickets: 1272
+
+ Fixed bug when using weak_instance_map=False where modified
+ events would not be intercepted for a flush().
+
+ .. change::
+ :tags: orm
+ :tickets: 1268
+
+ Fixed some deep "column correspondence" issues which could
+ impact a Query made against a selectable containing multiple
+ versions of the same table, as well as unions and similar
+ which contained the same table columns in different column
+ positions at different levels.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Custom comparator classes used in conjunction with
+ column_property(), relation() etc. can define new comparison
+ methods on the Comparator, which will become available via
+ __getattr__() on the InstrumentedAttribute. In the case of
+ synonym() or comparable_property(), attributes are resolved
+ first on the user-defined descriptor, then on the user-defined
+ comparator.
+
+ .. change::
+ :tags: orm
+ :tickets: 976
+
+ Added ScopedSession.is_active accessor.
+
+ .. change::
+ :tags: orm
+ :tickets: 1262
+
+ Can pass mapped attributes and column objects as keys to
+ query.update({}).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Mapped attributes passed to the values() of an expression
+ level insert() or update() will use the keys of the mapped
+ columns, not that of the mapped attribute.
+
+ .. change::
+ :tags: orm
+ :tickets: 1242
+
+ Corrected problem with Query.delete() and Query.update() not
+ working properly with bind parameters.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.select_from(), from_statement() ensure that the given
+ argument is a FromClause, or Text/Select/Union, respectively.
+
+ .. change::
+ :tags: orm
+ :tickets: 1253
+
+ Query() can be passed a "composite" attribute as a column
+ expression and it will be expanded. Somewhat related to.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query() is a little more robust when passed various column
+ expressions such as strings, clauselists, text() constructs
+ (which may mean it just raises an error more nicely).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ first() works as expected with Query.from_statement().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug introduced in 0.5rc4 involving eager loading not
+ functioning for properties which were added to a mapper
+ post-compile using add_property() or equivalent.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug where many-to-many relation() with viewonly=True
+ would not correctly reference the link between
+ secondary->remote.
+
+ .. change::
+ :tags: orm
+ :tickets: 1232
+
+ Duplicate items in a list-based collection will be maintained
+ when issuing INSERTs to a "secondary" table in a many-to-many
+ relation. Assuming the m2m table has a unique or primary key
+ constraint on it, this will raise the expected constraint
+ violation instead of silently dropping the duplicate
+ entries. Note that the old behavior remains for a one-to-many
+ relation since collection entries in that case don't result in
+ INSERT statements and SQLA doesn't manually police
+ collections.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.add_column() can accept FromClause objects in the same
+ manner as session.query() can.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Comparison of many-to-one relation to NULL is properly
+ converted to IS NOT NULL based on not_().
+
+ .. change::
+ :tags: orm
+ :tickets: 1087
+
+ Extra checks added to ensure explicit
+ primaryjoin/secondaryjoin are ClauseElement instances, to
+ prevent more confusing errors later on.
+
+ .. change::
+ :tags: orm
+ :tickets: 1236
+
+ Improved mapper() check for non-class classes.
+
+ .. change::
+ :tags: orm
+ :tickets: 5051
+
+ comparator_factory argument is now documented and supported by
+ all MapperProperty types, including column_property(),
+ relation(), backref(), and synonym().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Changed the name of PropertyLoader to RelationProperty, to be
+ consistent with all the other names. PropertyLoader is still
+ present as a synonym.
+
+ .. change::
+ :tags: orm
+ :tickets: 1099, 1228
+
+ fixed "double iter()" call causing bus errors in shard API,
+ removed errant result.close() left over from the 0.4
+ version.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ made Session.merge cascades not trigger autoflush. Fixes
+ merged instances getting prematurely inserted with missing
+ values.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Two fixes to help prevent out-of-band columns from being
+ rendered in polymorphic_union inheritance scenarios (which
+ then causes extra tables to be rendered in the FROM clause
+ causing cartesian products):
+
+ - improvements to "column adaption" for a->b->c inheritance
+ situations to better locate columns that are related to
+ one another via multiple levels of indirection, rather
+ than rendering the non-adapted column.
+
+ - the "polymorphic discriminator" column is only rendered
+ for the actual mapper being queried against. The column
+ won't be "pulled in" from a subclass or superclass mapper
+ since it's not needed.
+
+ .. change::
+ :tags: orm
+ :tickets: 1072
+
+ Fixed shard_id argument on ShardedSession.execute().
+
+ .. change::
+ :tags: sql
+ :tickets: 1256
+
+ Columns can again contain percent signs within their
+ names.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ sqlalchemy.sql.expression.Function is now a public class. It
+ can be subclassed to provide user-defined SQL functions in an
+ imperative style, including with pre-established behaviors.
+ The postgis.py example illustrates one usage of this.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ PickleType now favors == comparison by default, if the
+ incoming object (such as a dict) implements __eq__(). If the
+ object does not implement __eq__() and mutable=True, a
+ deprecation warning is raised.
+
+ .. change::
+ :tags: sql
+ :tickets: 1215
+
+ Fixed the import weirdness in sqlalchemy.sql to not export
+ __names__.
+
+ .. change::
+ :tags: sql
+ :tickets: 1238
+
+ Using the same ForeignKey object repeatedly raises an error
+ instead of silently failing later.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added NotImplementedError for params() method on
+ Insert/Update/Delete constructs. These items currently don't
+ support this functionality, which also would be a little
+ misleading compared to values().
+
+ .. change::
+ :tags: sql
+ :tickets: 650
+
+ Reflected foreign keys will properly locate their referenced
+ column, even if the column was given a "key" attribute
+ different from the reflected name. This is achieved via a new
+ flag on ForeignKey/ForeignKeyConstraint called "link_to_name",
+ if True means the given name is the referred-to column's name,
+ not its assigned key.
+
+ .. change::
+ :tags: sql
+ :tickets: 1253
+
+ select() can accept a ClauseList as a column in the same way
+ as a Table or other selectable and the interior expressions
+ will be used as column elements.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the "passive" flag on session.is_modified() is correctly
+ propagated to the attribute manager.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ union() and union_all() will not whack any order_by() that has
+ been applied to the select()s inside. If you union() a
+ select() with order_by() (presumably to support LIMIT/OFFSET),
+ you should also call self_group() on it to apply parenthesis.
+
+ .. change::
+ :tags: engine/pool
+ :tickets: 1246
+
+ Connection.invalidate() checks for closed status to avoid
+ attribute errors.
+
+ .. change::
+ :tags: engine/pool
+ :tickets: 1094
+
+ NullPool supports reconnect on failure behavior.
+
+ .. change::
+ :tags: engine/pool
+ :tickets: 799
+
+ Added a mutex for the initial pool creation when using
+ pool.manage(dbapi). This prevents a minor case of "dogpile"
+ behavior which would otherwise occur upon a heavy load
+ startup.
+
+ .. change::
+ :tags: engine/pool
+ :tickets:
+
+ _execute_clauseelement() goes back to being a private method.
+ Subclassing Connection is not needed now that ConnectionProxy
+ is available.
+
+ .. change::
+ :tags: documentation
+ :tickets: 1149, 1200
+
+ Tickets.
+
+ .. change::
+ :tags: documentation
+ :tickets:
+
+ Added note about create_session() defaults.
+
+ .. change::
+ :tags: documentation
+ :tickets:
+
+ Added section about metadata.reflect().
+
+ .. change::
+ :tags: documentation
+ :tickets:
+
+ Updated `TypeDecorator` section.
+
+ .. change::
+ :tags: documentation
+ :tickets:
+
+ Rewrote the "threadlocal" strategy section of the docs due to
+ recent confusion over this feature.
+
+ .. change::
+ :tags: documentation
+ :tickets:
+
+ Removed badly out of date 'polymorphic_fetch' and
+ 'select_table' docs from inheritance, reworked the second half
+ of "joined table inheritance".
+
+ .. change::
+ :tags: documentation
+ :tickets:
+
+ Documented `comparator_factory` kwarg, added new doc section
+ "Custom Comparators".
+
+ .. change::
+ :tags: mssql
+ :tickets: 1254
+
+ Refactored the Date/Time types. The ``smalldatetime`` data
+ type no longer truncates to a date only, and will now be
+ mapped to the MSSmallDateTime type.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Corrected an issue with Numerics to accept an int.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Mapped ``char_length`` to the ``LEN()`` function.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ If an ``INSERT`` includes a subselect the ``INSERT`` is
+ converted from an ``INSERT INTO VALUES`` construct to a
+ ``INSERT INTO SELECT`` construct.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ If the column is part of a ``primary_key`` it will be ``NOT
+ NULL`` since MSSQL doesn't allow ``NULL`` in primary_key
+ columns.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1249
+
+ ``MSBinary`` now returns a ``BINARY`` instead of an
+ ``IMAGE``. This is a backwards incompatible change in that
+ ``BINARY`` is a fixed length data type whereas ``IMAGE`` is a
+ variable length data type.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1258
+
+ ``get_default_schema_name`` is now reflected from the database
+ based on the user's default schema. This only works with MSSQL
+ 2005 and later.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1248
+
+ Added collation support through the use of a new collation
+ argument. This is supported on the following types: char,
+ nchar, varchar, nvarchar, text, ntext.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Changes to the connection string parameters favor DSN as the
+ default specification for pyodbc. See the mssql.py docstring
+ for detailed usage instructions.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Added experimental support of savepoints. It currently does
+ not work fully with sessions.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1243
+
+ Support for three levels of column nullability: NULL, NOT
+ NULL, and the database's configured default. The default
+ Column configuration (nullable=True) will now generate NULL in
+ the DDL. Previously no specification was emitted and the
+ database default would take effect (usually NULL, but not
+ always). To explicitly request the database default,
+ configure columns with nullable=None and no specification will
+ be emitted in DDL. This is backwards incompatible
+ behavior.
+
+ .. change::
+ :tags: postgres
+ :tickets: 1267
+
+ "%" signs in text() constructs are automatically escaped to
+ "%%". Because of the backwards incompatible nature of this
+ change, a warning is emitted if '%%' is detected in the
+ string.
+
+ .. change::
+ :tags: postgres
+ :tickets:
+
+ Calling alias.execute() in conjunction with
+ server_side_cursors won't raise AttributeError.
+
+ .. change::
+ :tags: postgres
+ :tickets: 714
+
+ Added Index reflection support to PostgreSQL, using a great
+ patch we long neglected, submitted by Ken
+ Kuhlman.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Adjusted the format of create_xid() to repair two-phase
+ commit. We now have field reports of Oracle two-phase commit
+ working properly with this change.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1233
+
+ Added OracleNVarchar type, produces NVARCHAR2, and also
+ subclasses Unicode so that convert_unicode=True by default.
+ NVARCHAR2 reflects into this type automatically so these
+ columns pass unicode on a reflected table with no explicit
+ convert_unicode=True flags.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1265
+
+ Fixed bug which was preventing out params of certain types
+ from being received; thanks a ton to huddlej at wwu.edu !
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ "%" signs in text() constructs are automatically escaped to
+ "%%". Because of the backwards incompatible nature of this
+ change, a warning is emitted if '%%' is detected in the
+ string.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1241
+
+ Fixed bug in exception raise when FK columns not present
+ during reflection.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Fixed bug involving reflection of a remote-schema table with a
+ foreign key ref to another table in that schema.
+
+ .. change::
+ :tags: associationproxy
+ :tickets:
+
+ The association proxy properties are make themselves available
+ at the class level, e.g. MyClass.aproxy. Previously this
+ evaluated to None.
+
+ .. change::
+ :tags: declarative
+ :tickets:
+
+ The full list of arguments accepted as string by backref()
+ includes 'primaryjoin', 'secondaryjoin', 'secondary',
+ 'foreign_keys', 'remote_side', 'order_by'.
+
+.. changelog::
+ :version: 0.5.0rc4
+ :released: Fri Nov 14 2008
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.count() has been enhanced to do the "right thing" in a
+ wider variety of cases. It can now count multiple-entity
+ queries, as well as column-based queries. Note that this means
+ if you say query(A, B).count() without any joining criterion,
+ it's going to count the cartesian product of A*B. Any query
+ which is against column-based entities will automatically
+ issue "SELECT count(1) FROM (SELECT...)" so that the real
+ rowcount is returned, meaning a query such as
+ query(func.count(A.name)).count() will return a value of one,
+ since that query would return one row.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Lots of performance tuning. A rough guesstimate over various
+ ORM operations places it 10% faster over 0.5.0rc3, 25-30% over
+ 0.4.8.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ bugfixes and behavioral changes
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ global "propigate"->"propagate" change.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Adjustments to the enhanced garbage collection on
+ InstanceState to better guard against errors due to lost
+ state.
+
+ .. change::
+ :tags: orm
+ :tickets: 1220
+
+ Query.get() returns a more informative error message when
+ executed against multiple entities.
+
+ .. change::
+ :tags: orm
+ :tickets: 1140, 1221
+
+ Restored NotImplementedError on Cls.relation.in_()
+
+ .. change::
+ :tags: orm
+ :tickets: 1226
+
+ Fixed PendingDeprecationWarning involving order_by parameter
+ on relation().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Removed the 'properties' attribute of the Connection object,
+ Connection.info should be used.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Restored "active rowcount" fetch before ResultProxy autocloses
+ the cursor. This was removed in 0.5rc3.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Rearranged the `load_dialect_impl()` method in `TypeDecorator`
+ such that it will take effect even if the user-defined
+ `TypeDecorator` uses another `TypeDecorator` as its impl.
+
+ .. change::
+ :tags: access
+ :tickets:
+
+ Added support for Currency type.
+
+ .. change::
+ :tags: access
+ :tickets: 1017
+
+ Functions were not return their result.
+
+ .. change::
+ :tags: access
+ :tickets: 1017
+
+ Corrected problem with joins. Access only support LEFT OUTER
+ or INNER not just JOIN by itself.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Lots of cleanup and fixes to correct problems with limit and
+ offset.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Correct situation where subqueries as part of a binary
+ expression need to be translated to use the IN and NOT IN
+ syntax.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1216
+
+ Fixed E Notation issue that prevented the ability to insert
+ decimal values less than 1E-6.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1217
+
+ Corrected problems with reflection when dealing with schemas,
+ particularly when those schemas are the default
+ schema.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Corrected problem with casting a zero length item to a
+ varchar. It now correctly adjusts the CAST.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ Can now use a custom "inherit_condition" in __mapper_args__
+ when using declarative.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ fixed string-based "remote_side", "order_by" and others not
+ propagating correctly when used in backref().
+
+.. changelog::
+ :version: 0.5.0rc3
+ :released: Fri Nov 07 2008
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added two new hooks to SessionExtension: after_bulk_delete()
+ and after_bulk_update(). after_bulk_delete() is called after
+ a bulk delete() operation on a query. after_bulk_update() is
+ called after a bulk update() operation on a query.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ SQL compiler optimizations and complexity reduction. The call
+ count for compiling a typical select() construct is 20% less
+ versus 0.5.0rc2.
+
+ .. change::
+ :tags: sql
+ :tickets: 1211
+
+ Dialects can now generate label names of adjustable
+ length. Pass in the argument "label_length=<value>" to
+ create_engine() to adjust how many characters max will be
+ present in dynamically generated column labels, i.e.
+ "somecolumn AS somelabel". Any value less than 6 will result
+ in a label of minimal size, consisting of an underscore and a
+ numeric counter. The compiler uses the value of
+ dialect.max_identifier_length as a default.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ Added a new extension sqlalchemy.ext.serializer. Provides
+ Serializer/Deserializer "classes" which mirror
+ Pickle/Unpickle, as well as dumps() and loads(). This
+ serializer implements an "external object" pickler which keeps
+ key context-sensitive objects, including engines, sessions,
+ metadata, Tables/Columns, and mappers, outside of the pickle
+ stream, and can later restore the pickle using any
+ engine/metadata/session provider. This is used not for
+ pickling regular object instances, which are pickleable
+ without any special logic, but for pickling expression objects
+ and full Query objects, such that all mapper/engine/session
+ dependencies can be restored at unpickle time.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Wrote a docstring for Oracle dialect. Apparently that Ohloh
+ "few source code comments" label is starting to sting :).
+
+ .. change::
+ :tags: oracle
+ :tickets: 536
+
+ Removed FIRST_ROWS() optimize flag when using LIMIT/OFFSET,
+ can be reenabled with optimize_limits=True create_engine()
+ flag.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ bugfixes and behavioral changes
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ "not equals" comparisons of simple many-to-one relation to an
+ instance will not drop into an EXISTS clause and will compare
+ foreign key columns instead.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Removed not-really-working use cases of comparing a collection
+ to an iterable. Use contains() to test for collection
+ membership.
+
+ .. change::
+ :tags: orm
+ :tickets: 1171
+
+ Improved the behavior of aliased() objects such that they more
+ accurately adapt the expressions generated, which helps
+ particularly with self-referential comparisons.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug involving primaryjoin/secondaryjoin conditions
+ constructed from class-bound attributes (as often occurs when
+ using declarative), which later would be inappropriately
+ aliased by Query, particularly with the various EXISTS based
+ comparators.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug when using multiple query.join() with an
+ aliased-bound descriptor which would lose the left alias.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Improved weakref identity map memory management to no longer
+ require mutexing, resurrects garbage collected instance on a
+ lazy basis for an InstanceState with pending changes.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ InstanceState object now removes circular references to itself
+ upon disposal to keep it outside of cyclic garbage collection.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ relation() won't hide unrelated ForeignKey errors inside of
+ the "please specify primaryjoin" message when determining join
+ condition.
+
+ .. change::
+ :tags: orm
+ :tickets: 1218
+
+ Fixed bug in Query involving order_by() in conjunction with
+ multiple aliases of the same class (will add tests in)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ When using Query.join() with an explicit clause for the ON
+ clause, the clause will be aliased in terms of the left side
+ of the join, allowing scenarios like query(Source).
+ from_self().join((Dest, Source.id==Dest.source_id)) to work
+ properly.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ polymorphic_union() function respects the "key" of each Column
+ if they differ from the column's name.
+
+ .. change::
+ :tags: orm
+ :tickets: 1183
+
+ Repaired support for "passive-deletes" on a many-to-one
+ relation() with "delete" cascade.
+
+ .. change::
+ :tags: orm
+ :tickets: 1213
+
+ Fixed bug in composite types which prevented a primary-key
+ composite type from being mutated.
+
+ .. change::
+ :tags: orm
+ :tickets: 1202
+
+ Added more granularity to internal attribute access, such that
+ cascade and flush operations will not initialize unloaded
+ attributes and collections, leaving them intact for a
+ lazy-load later on. Backref events still initialize attrbutes
+ and collections for pending instances.
+
+ .. change::
+ :tags: sql
+ :tickets: 1212
+
+ Simplified the check for ResultProxy "autoclose without
+ results" to be based solely on presence of
+ cursor.description. All the regexp-based guessing about
+ statements returning rows has been removed.
+
+ .. change::
+ :tags: sql
+ :tickets: 1194
+
+ Direct execution of a union() construct will properly set up
+ result-row processing.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The internal notion of an "OID" or "ROWID" column has been
+ removed. It's basically not used by any dialect, and the
+ possibility of its usage with psycopg2's cursor.lastrowid is
+ basically gone now that INSERT..RETURNING is available.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Removed "default_order_by()" method on all FromClause objects.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Repaired the table.tometadata() method so that a passed-in
+ schema argument is propagated to ForeignKey constructs.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Slightly changed behavior of IN operator for comparing to
+ empty collections. Now results in inequality comparison
+ against self. More portable, but breaks with stored procedures
+ that aren't pure functions.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Setting the auto_convert_lobs to False on create_engine() will
+ also instruct the OracleBinary type to return the cx_oracle
+ LOB object unchanged.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Fixed foreign key reflection in the edge case where a Table's
+ explicit schema= is the same as the schema (database) the
+ connection is attached to.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ No longer expects include_columns in table reflection to be
+ lower case.
+
+ .. change::
+ :tags: ext
+ :tickets: 1174
+
+ Fixed bug preventing declarative-bound "column" objects from
+ being used in column_mapped_collection().
+
+ .. change::
+ :tags: misc
+ :tickets: 1077
+
+ util.flatten_iterator() func doesn't interpret strings with
+ __iter__() methods as iterators, such as in pypy.
+
+.. changelog::
+ :version: 0.5.0rc2
+ :released: Sun Oct 12 2008
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug involving read/write relation()s that contain
+ literal or other non-column expressions within their
+ primaryjoin condition equated to a foreign key column.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ "non-batch" mode in mapper(), a feature which allows mapper
+ extension methods to be called as each instance is
+ updated/inserted, now honors the insert order of the objects
+ given.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed RLock-related bug in mapper which could deadlock upon
+ reentrant mapper compile() calls, something that occurs when
+ using declarative constructs inside of ForeignKey objects.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ ScopedSession.query_property now accepts a query_cls factory,
+ overriding the session's configured query_cls.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed shared state bug interfering with ScopedSession.mapper's
+ ability to apply default __init__ implementations on object
+ subclasses.
+
+ .. change::
+ :tags: orm
+ :tickets: 1177
+
+ Fixed up slices on Query (i.e. query[x:y]) to work properly
+ for zero length slices, slices with None on either end.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added an example illustrating Celko's "nested sets" as a
+ SQLA mapping.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ contains_eager() with an alias argument works even when
+ the alias is embedded in a SELECT, as when sent to the
+ Query via query.select_from().
+
+ .. change::
+ :tags: orm
+ :tickets: 1180
+
+ contains_eager() usage is now compatible with a Query that
+ also contains a regular eager load and limit/offset, in that
+ the columns are added to the Query-generated subquery.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ session.execute() will execute a Sequence object passed to
+ it (regression from 0.4).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Removed the "raiseerror" keyword argument from object_mapper()
+ and class_mapper(). These functions raise in all cases
+ if the given class/instance is not mapped.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed session.transaction.commit() on a autocommit=False
+ session not starting a new transaction.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Some adjustments to Session.identity_map's weak referencing
+ behavior to reduce asynchronous GC side effects.
+
+ .. change::
+ :tags: orm
+ :tickets: 1182
+
+ Adjustment to Session's post-flush accounting of newly
+ "clean" objects to better protect against operating on
+ objects as they're asynchronously gc'ed.
+
+ .. change::
+ :tags: sql
+ :tickets: 1074
+
+ column.in_(someselect) can now be used as a columns-clause
+ expression without the subquery bleeding into the FROM clause
+
+ .. change::
+ :tags: sqlite
+ :tickets: 968
+
+ Overhauled SQLite date/time bind/result processing to use
+ regular expressions and format strings, rather than
+ strptime/strftime, to generically support pre-1900 dates,
+ dates with microseconds.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ String's (and Unicode's, UnicodeText's, etc.) convert_unicode
+ logic disabled in the sqlite dialect, to adjust for pysqlite
+ 2.5.0's new requirement that only Python unicode objects are
+ accepted;
+ http://itsystementwicklung.de/pipermail/list-pysqlite/2008-March/000018.html
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Temporary tables are now reflectable.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1187
+
+ Oracle will detect string-based statements which contain
+ comments at the front before a SELECT as SELECT statements.
+
+.. changelog::
+ :version: 0.5.0rc1
+ :released: Thu Sep 11 2008
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query now has delete() and update(values) methods. This allows
+ to perform bulk deletes/updates with the Query object.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The RowTuple object returned by Query(*cols) now features
+ keynames which prefer mapped attribute names over column keys,
+ column keys over column names, i.e. Query(Class.foo,
+ Class.bar) will have names "foo" and "bar" even if those are
+ not the names of the underlying Column objects. Direct Column
+ objects such as Query(table.c.col) will return the "key"
+ attribute of the Column.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added scalar() and value() methods to Query, each return a
+ single scalar value. scalar() takes no arguments and is
+ roughly equivalent to first()[0], value()
+ takes a single column expression and is roughly equivalent to
+ values(expr).next()[0].
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Improved the determination of the FROM clause when placing SQL
+ expressions in the query() list of entities. In particular
+ scalar subqueries should not "leak" their inner FROM objects
+ out into the enclosing query.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Joins along a relation() from a mapped class to a mapped
+ subclass, where the mapped subclass is configured with single
+ table inheritance, will include an IN clause which limits the
+ subtypes of the joined class to those requested, within the ON
+ clause of the join. This takes effect for eager load joins as
+ well as query.join(). Note that in some scenarios the IN
+ clause will appear in the WHERE clause of the query as well
+ since this discrimination has multiple trigger points.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ AttributeExtension has been refined such that the event
+ is fired before the mutation actually occurs. Additionally,
+ the append() and set() methods must now return the given value,
+ which is used as the value to be used in the mutation operation.
+ This allows creation of validating AttributeListeners which
+ raise before the action actually occurs, and which can change
+ the given value into something else before its used.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ column_property(), composite_property(), and relation() now
+ accept a single or list of AttributeExtensions using the
+ "extension" keyword argument.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.order_by().get() silently drops the "ORDER BY" from
+ the query issued by GET but does not raise an exception.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added a Validator AttributeExtension, as well as a
+ @validates decorator which is used in a similar fashion
+ as @reconstructor, and marks a method as validating
+ one or more mapped attributes.
+
+ .. change::
+ :tags: orm
+ :tickets: 1140
+
+ class.someprop.in_() raises NotImplementedError pending the
+ implementation of "in_" for relation
+
+ .. change::
+ :tags: orm
+ :tickets: 1127
+
+ Fixed primary key update for many-to-many collections where
+ the collection had not been loaded yet
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug whereby deferred() columns with a group in conjunction
+ with an otherwise unrelated synonym() would produce
+ an AttributeError during deferred load.
+
+ .. change::
+ :tags: orm
+ :tickets: 1128
+
+ The before_flush() hook on SessionExtension takes place before
+ the list of new/dirty/deleted is calculated for the final
+ time, allowing routines within before_flush() to further
+ change the state of the Session before the flush proceeds.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The "extension" argument to Session and others can now
+ optionally be a list, supporting events sent to multiple
+ SessionExtension instances. Session places SessionExtensions
+ in Session.extensions.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Reentrant calls to flush() raise an error. This also serves
+ as a rudimentary, but not foolproof, check against concurrent
+ calls to Session.flush().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Improved the behavior of query.join() when joining to
+ joined-table inheritance subclasses, using explicit join
+ criteria (i.e. not on a relation).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ @orm.attributes.reconstitute and
+ MapperExtension.reconstitute have been renamed to
+ @orm.reconstructor and MapperExtension.reconstruct_instance
+
+ .. change::
+ :tags: orm
+ :tickets: 1129
+
+ Fixed @reconstructor hook for subclasses which inherit from a
+ base class.
+
+ .. change::
+ :tags: orm
+ :tickets: 1132
+
+ The composite() property type now supports a
+ __set_composite_values__() method on the composite class which
+ is required if the class represents state using attribute
+ names other than the column's keynames; default-generated
+ values now get populated properly upon flush. Also,
+ composites with attributes set to None compare correctly.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The 3-tuple of iterables returned by attributes.get_history()
+ may now be a mix of lists and tuples. (Previously members
+ were always lists.)
+
+ .. change::
+ :tags: orm
+ :tickets: 1151
+
+ Fixed bug whereby changing a primary key attribute on an
+ entity where the attribute's previous value had been expired
+ would produce an error upon flush().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed custom instrumentation bug whereby get_instance_dict()
+ was not called for newly constructed instances not loaded
+ by the ORM.
+
+ .. change::
+ :tags: orm
+ :tickets: 1150
+
+ Session.delete() adds the given object to the session if
+ not already present. This was a regression bug from 0.4.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The `echo_uow` flag on `Session` is deprecated, and unit-of-work
+ logging is now application-level only, not per-session level.
+
+ .. change::
+ :tags: orm
+ :tickets: 1153
+
+ Removed conflicting `contains()` operator from
+ `InstrumentedAttribute` which didn't accept `escape` kwaarg.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1161
+
+ Fixed bug whereby mapper couldn't initialize if a composite
+ primary key referenced another table that was not defined
+ yet.
+
+ .. change::
+ :tags: declarative
+ :tickets:
+
+ Fixed exception throw which would occur when string-based
+ primaryjoin condition was used in conjunction with backref.
+
+ .. change::
+ :tags: schema
+ :tickets: 1033
+
+ Added "sorted_tables" accessor to MetaData, which returns
+ Table objects sorted in order of dependency as a list.
+ This deprecates the MetaData.table_iterator() method.
+ The "reverse=False" keyword argument has also been
+ removed from util.sort_tables(); use the Python
+ 'reversed' function to reverse the results.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ The 'length' argument to all Numeric types has been renamed
+ to 'scale'. 'length' is deprecated and is still accepted
+ with a warning.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Dropped 0.3-compatibility for user defined types
+ (convert_result_value, convert_bind_param).
+
+ .. change::
+ :tags: sql
+ :tickets: 1068
+
+ Temporarily rolled back the "ORDER BY" enhancement from. This feature is on hold pending further
+ development.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The exists() construct won't "export" its contained list
+ of elements as FROM clauses, allowing them to be used more
+ effectively in the columns clause of a SELECT.
+
+ .. change::
+ :tags: sql
+ :tickets: 798
+
+ and_() and or_() now generate a ColumnElement, allowing
+ boolean expressions as result columns, i.e.
+ select([and_(1, 0)]).
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Bind params now subclass ColumnElement which allows them to be
+ selectable by orm.query (they already had most ColumnElement
+ semantics).
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added select_from() method to exists() construct, which becomes
+ more and more compatible with a regular select().
+
+ .. change::
+ :tags: sql
+ :tickets: 1160
+
+ Added func.min(), func.max(), func.sum() as "generic functions",
+ which basically allows for their return type to be determined
+ automatically. Helps with dates on SQLite, decimal types,
+ others.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ added decimal.Decimal as an "auto-detect" type; bind parameters
+ and generic functions will set their type to Numeric when a
+ Decimal is used.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ The 'length' argument to MSInteger, MSBigInteger, MSTinyInteger,
+ MSSmallInteger and MSYear has been renamed to 'display_width'.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1146
+
+ Added MSMediumInteger type.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ the function func.utc_timestamp() compiles to UTC_TIMESTAMP, without
+ the parenthesis, which seem to get in the way when using in
+ conjunction with executemany().
+
+ .. change::
+ :tags: oracle
+ :tickets: 536
+
+ limit/offset no longer uses ROW NUMBER OVER to limit rows,
+ and instead uses subqueries in conjunction with a special
+ Oracle optimization comment. Allows LIMIT/OFFSET to work
+ in conjunction with DISTINCT.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1155
+
+ has_sequence() now takes the current "schema" argument into
+ account
+
+ .. change::
+ :tags: oracle
+ :tickets: 1121
+
+ added BFILE to reflected type names
+
+.. changelog::
+ :version: 0.5.0beta3
+ :released: Mon Aug 04 2008
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The "entity_name" feature of SQLAlchemy mappers has been
+ removed. For rationale, see http://tinyurl.com/6nm2ne
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the "autoexpire" flag on Session, sessionmaker(), and
+ scoped_session() has been renamed to "expire_on_commit". It
+ does not affect the expiration behavior of rollback().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ fixed endless loop bug which could occur within a mapper's
+ deferred load of inherited attributes.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ a legacy-support flag "_enable_transaction_accounting" flag
+ added to Session which when False, disables all
+ transaction-level object accounting, including expire on
+ rollback, expire on commit, new/deleted list maintenance, and
+ autoflush on begin.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The 'cascade' parameter to relation() accepts None as a value,
+ which is equivalent to no cascades.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ A critical fix to dynamic relations allows the "modified"
+ history to be properly cleared after a flush().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ user-defined @properties on a class are detected and left in
+ place during mapper initialization. This means that a
+ table-bound column of the same name will not be mapped at all
+ if a @property is in the way (and the column is not remapped
+ to a different name), nor will an instrumented attribute from
+ an inherited class be applied. The same rules apply for names
+ excluded using the include_properties/exclude_properties
+ collections.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added a new SessionExtension hook called after_attach(). This
+ is called at the point of attachment for objects via add(),
+ add_all(), delete(), and merge().
+
+ .. change::
+ :tags: orm
+ :tickets: 1111
+
+ A mapper which inherits from another, when inheriting the
+ columns of its inherited mapper, will use any reassigned
+ property names specified in that inheriting mapper.
+ Previously, if "Base" had reassigned "base_id" to the name
+ "id", "SubBase(Base)" would still get an attribute called
+ "base_id". This could be worked around by explicitly stating
+ the column in each submapper as well but this is fairly
+ unworkable and also impossible when using declarative.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed a series of potential race conditions in Session whereby
+ asynchronous GC could remove unmodified, no longer referenced
+ items from the session as they were present in a list of items
+ to be processed, typically during session.expunge_all() and
+ dependent methods.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Some improvements to the _CompileOnAttr mechanism which should
+ reduce the probability of "Attribute x was not replaced during
+ compile" warnings. (this generally applies to SQLA hackers,
+ like Elixir devs).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug whereby the "unsaved, pending instance" FlushError
+ raised for a pending orphan would not take superclass mappers
+ into account when generating the list of relations responsible
+ for the error.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ func.count() with no arguments renders as COUNT(*), equivalent
+ to func.count(text('*')).
+
+ .. change::
+ :tags: sql
+ :tickets: 1068
+
+ simple label names in ORDER BY expressions render as
+ themselves, and not as a re-statement of their corresponding
+ expression. This feature is currently enabled only for
+ SQLite, MySQL, and PostgreSQL. It can be enabled on other
+ dialects as each is shown to support this
+ behavior.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ Class-bound attributes sent as arguments to relation()'s
+ remote_side and foreign_keys parameters are now accepted,
+ allowing them to be used with declarative. Additionally fixed
+ bugs involving order_by being specified as a class-bound
+ attribute in conjunction with eager loading.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ declarative initialization of Columns adjusted so that
+ non-renamed columns initialize in the same way as a non
+ declarative mapper. This allows an inheriting mapper to set
+ up its same-named "id" columns in particular such that the
+ parent "id" column is favored over the child column, reducing
+ database round trips when this value is requested.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1110
+
+ Quoting of MSEnum values for use in CREATE TABLE is now
+ optional & will be quoted on demand as required. (Quoting was
+ always optional for use with existing tables.)
+
+.. changelog::
+ :version: 0.5.0beta2
+ :released: Mon Jul 14 2008
+
+ .. change::
+ :tags: orm
+ :tickets: 870
+
+ In addition to expired attributes, deferred attributes also
+ load if their data is present in the result set.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ session.refresh() raises an informative error message if the
+ list of attributes does not include any column-based
+ attributes.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query() raises an informative error message if no columns or
+ mappers are specified.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ lazy loaders now trigger autoflush before proceeding. This
+ allows expire() of a collection or scalar relation to function
+ properly in the context of autoflush.
+
+ .. change::
+ :tags: orm
+ :tickets: 887
+
+ column_property() attributes which represent SQL expressions
+ or columns that are not present in the mapped tables (such as
+ those from views) are automatically expired after an INSERT or
+ UPDATE, assuming they have not been locally modified, so that
+ they are refreshed with the most recent data upon access.
+
+ .. change::
+ :tags: orm
+ :tickets: 1082
+
+ Fixed explicit, self-referential joins between two
+ joined-table inheritance mappers when using query.join(cls,
+ aliased=True).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed query.join() when used in conjunction with a
+ columns-only clause and an SQL-expression ON clause in the
+ join.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The "allow_column_override" flag from mapper() has been
+ removed. This flag is virtually always misunderstood. Its
+ specific functionality is available via the
+ include_properties/exclude_properties mapper arguments.
+
+ .. change::
+ :tags: orm
+ :tickets: 1066
+
+ Repaired `__str__()` method on Query.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session.bind gets used as a default even when table/mapper
+ specific binds are defined.
+
+ .. change::
+ :tags: schema
+ :tickets: 1075
+
+ Added prefixes option to `Table` that accepts a list of
+ strings to insert after CREATE in the CREATE TABLE statement.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Unicode, UnicodeText types now set "assert_unicode" and
+ "convert_unicode" by default, but accept overriding
+ **kwargs for these values.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added new match() operator that performs a full-text search.
+ Supported on PostgreSQL, SQLite, MySQL, MS-SQL, and Oracle
+ backends.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 1090
+
+ Modified SQLite's representation of "microseconds" to match
+ the output of str(somedatetime), i.e. in that the microseconds
+ are represented as fractional seconds in string format. This
+ makes SQLA's SQLite date type compatible with datetimes that
+ were saved directly using Pysqlite (which just calls str()).
+ Note that this is incompatible with the existing microseconds
+ values in a SQLA 0.4 generated SQLite database file.
+
+ To get the old behavior globally:
+
+ from sqlalchemy.databases.sqlite import DateTimeMixin
+ DateTimeMixin.__legacy_microseconds__ = True
+
+ To get the behavior on individual DateTime types:
+
+ t = sqlite.SLDateTime()
+ t.__legacy_microseconds__ = True
+
+ Then use "t" as the type on the Column.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ SQLite Date, DateTime, and Time types only accept Python
+ datetime objects now, not strings. If you'd like to format
+ dates as strings yourself with SQLite, use a String type. If
+ you'd like them to return datetime objects anyway despite
+ their accepting strings as input, make a TypeDecorator around
+ String - SQLA doesn't encourage this pattern.
+
+ .. change::
+ :tags: extensions
+ :tickets: 1096
+
+ Declarative supports a __table_args__ class variable, which is
+ either a dictionary, or tuple of the form (arg1, arg2, ...,
+ {kwarg1:value, ...}) which contains positional + kw arguments
+ to be passed to the Table constructor.
+
+.. changelog::
+ :version: 0.5.0beta1
+ :released: Thu Jun 12 2008
+
+ .. change::
+ :tags:
+ :tickets:
+
+ The "__init__" trigger/decorator added by mapper now attempts
+ to exactly mirror the argument signature of the original
+ __init__. The pass-through for '_sa_session' is no longer
+ implicit- you must allow for this keyword argument in your
+ constructor.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ ClassState is renamed to ClassManager.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Classes may supply their own InstrumentationManager by
+ providing a __sa_instrumentation_manager__ property.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Custom instrumentation may use any mechanism to associate a
+ ClassManager with a class and an InstanceState with an
+ instance. Attributes on those objects are still the default
+ association mechanism used by SQLAlchemy's native
+ instrumentation.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Moved entity_name, _sa_session_id, and _instance_key from the
+ instance object to the instance state. These values are still
+ available in the old way, which is now deprecated, using
+ descriptors attached to the class. A deprecation warning will
+ be issued when accessed.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ The _prepare_instrumentation alias for prepare_instrumentation
+ has been removed.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ sqlalchemy.exceptions has been renamed to sqlalchemy.exc. The
+ module may be imported under either name.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ ORM-related exceptions are now defined in sqlalchemy.orm.exc.
+ ConcurrentModificationError, FlushError, and
+ UnmappedColumnError compatibility aliases are installed in
+ sqlalchemy.exc during the import of sqlalchemy.orm.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ sqlalchemy.logging has been renamed to sqlalchemy.log.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ The transitional sqlalchemy.log.SADeprecationWarning alias for
+ the warning's definition in sqlalchemy.exc has been removed.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ exc.AssertionError has been removed and usage replaced with
+ Python's built-in AssertionError.
+
+ .. change::
+ :tags:
+ :tickets:
+
+ The behavior of MapperExtensions attached to multiple,
+ entity_name= primary mappers for a single class has been
+ altered. The first mapper() defined for a class is the only
+ mapper eligible for the MapperExtension 'instrument_class',
+ 'init_instance' and 'init_failed' events. This is backwards
+ incompatible; previously the extensions of last mapper defined
+ would receive these events.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ Added support for returning values from inserts (2.0+ only),
+ updates and deletes (2.1+ only).
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ global "propigate"->"propagate" change.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ polymorphic_union() function respects the "key" of each
+ Column if they differ from the column's name.
+
+ .. change::
+ :tags: orm
+ :tickets: 1199
+
+ Fixed 0.4-only bug preventing composite columns
+ from working properly with inheriting mappers
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed RLock-related bug in mapper which could deadlock upon
+ reentrant mapper compile() calls, something that occurs when
+ using declarative constructs inside of ForeignKey objects.
+ Ported from 0.5.
+
+ .. change::
+ :tags: orm
+ :tickets: 1213
+
+ Fixed bug in composite types which prevented a primary-key
+ composite type from being mutated.
+
+ .. change::
+ :tags: orm
+ :tickets: 976
+
+ Added ScopedSession.is_active accessor.
+
+ .. change::
+ :tags: orm
+ :tickets: 939
+
+ Class-bound accessor can be used as the argument to
+ relation() order_by.
+
+ .. change::
+ :tags: orm
+ :tickets: 1072
+
+ Fixed shard_id argument on ShardedSession.execute().
+
+ .. change::
+ :tags: sql
+ :tickets: 1246
+
+ Connection.invalidate() checks for closed status
+ to avoid attribute errors.
+
+ .. change::
+ :tags: sql
+ :tickets: 1094
+
+ NullPool supports reconnect on failure behavior.
+
+ .. change::
+ :tags: sql
+ :tickets: 1299
+
+ The per-dialect cache used by TypeEngine to cache
+ dialect-specific types is now a WeakKeyDictionary.
+ This to prevent dialect objects from
+ being referenced forever for an application that
+ creates an arbitrarily large number of engines
+ or dialects. There is a small performance penalty
+ which will be resolved in 0.6.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed SQLite reflection methods so that non-present
+ cursor.description, which triggers an auto-cursor
+ close, will be detected so that no results doesn't
+ fail on recent versions of pysqlite which raise
+ an error when fetchone() called with no rows present.
+
+ .. change::
+ :tags: postgres
+ :tickets: 714
+
+ Added Index reflection support to Postgres, using a
+ great patch we long neglected, submitted by
+ Ken Kuhlman.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1241
+
+ Fixed bug in exception raise when FK columns not present
+ during reflection.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1265
+
+ Fixed bug which was preventing out params of certain types
+ from being received; thanks a ton to huddlej at wwu.edu !
--- /dev/null
+
+==============
+0.6 Changelog
+==============
+
+
+.. changelog::
+ :version: 0.6.9
+ :released: Sat May 05 2012
+
+ .. change::
+ :tags: general
+ :tickets: 2279
+
+ Adjusted the "importlater" mechanism, which is
+ used internally to resolve import cycles,
+ such that the usage of __import__ is completed
+ when the import of sqlalchemy or sqlalchemy.orm
+ is done, thereby avoiding any usage of __import__
+ after the application starts new threads,
+ fixes.
+
+ .. change::
+ :tags: orm
+ :tickets: 2197
+
+ Fixed bug whereby the source clause
+ used by query.join() would be inconsistent
+ if against a column expression that combined
+ multiple entities together.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2310
+
+ fixed inappropriate evaluation of user-mapped
+ object in a boolean context within query.get().
+
+ .. change::
+ :tags: orm
+ :tickets: 2228
+
+ Fixed bug apparent only in Python 3 whereby
+ sorting of persistent + pending objects during
+ flush would produce an illegal comparison,
+ if the persistent object primary key
+ is not a single integer.
+
+ .. change::
+ :tags: orm
+ :tickets: 2234
+
+ Fixed bug where query.join() + aliased=True
+ from a joined-inh structure to itself on
+ relationship() with join condition on the child
+ table would convert the lead entity into the
+ joined one inappropriately.
+
+ .. change::
+ :tags: orm
+ :tickets: 2287
+
+ Fixed bug whereby mapper.order_by attribute would
+ be ignored in the "inner" query within a
+ subquery eager load. .
+
+ .. change::
+ :tags: orm
+ :tickets: 2215
+
+ Fixed bug whereby if a mapped class
+ redefined __hash__() or __eq__() to something
+ non-standard, which is a supported use case
+ as SQLA should never consult these,
+ the methods would be consulted if the class
+ was part of a "composite" (i.e. non-single-entity)
+ result set.
+
+ .. change::
+ :tags: orm
+ :tickets: 2188
+
+ Fixed subtle bug that caused SQL to blow
+ up if: column_property() against subquery +
+ joinedload + LIMIT + order by the column
+ property() occurred. .
+
+ .. change::
+ :tags: orm
+ :tickets: 2207
+
+ The join condition produced by with_parent
+ as well as when using a "dynamic" relationship
+ against a parent will generate unique
+ bindparams, rather than incorrectly repeating
+ the same bindparam. .
+
+ .. change::
+ :tags: orm
+ :tickets: 2199
+
+ Repaired the "no statement condition"
+ assertion in Query which would attempt
+ to raise if a generative method were called
+ after from_statement() were called..
+
+ .. change::
+ :tags: orm
+ :tickets: 1776
+
+ Cls.column.collate("some collation") now
+ works.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2297
+
+ Fixed the error formatting raised when
+ a tuple is inadvertently passed to session.query().
+
+ .. change::
+ :tags: engine
+ :tickets: 2317
+
+ Backported the fix for introduced
+ in 0.7.4, which ensures that the connection
+ is in a valid state before attempting to call
+ rollback()/prepare()/release() on savepoint
+ and two-phase transactions.
+
+ .. change::
+ :tags: sql
+ :tickets: 2188
+
+ Fixed two subtle bugs involving column
+ correspondence in a selectable,
+ one with the same labeled subquery repeated, the other
+ when the label has been "grouped" and
+ loses itself. Affects.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed bug whereby "warn on unicode" flag
+ would get set for the String type
+ when used with certain dialects. This
+ bug is not in 0.7.
+
+ .. change::
+ :tags: sql
+ :tickets: 2270
+
+ Fixed bug whereby with_only_columns() method of
+ Select would fail if a selectable were passed.. However, the FROM behavior is
+ still incorrect here, so you need 0.7 in
+ any case for this use case to be usable.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Added an informative error message when
+ ForeignKeyConstraint refers to a column name in
+ the parent that is not found.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2291, 2141
+
+ Fixed bug related to whereby the
+ same modified index behavior in PG 9 affected
+ primary key reflection on a renamed column..
+
+ .. change::
+ :tags: mysql
+ :tickets: 2186
+
+ Fixed OurSQL dialect to use ansi-neutral
+ quote symbol "'" for XA commands instead
+ of '"'. .
+
+ .. change::
+ :tags: mysql
+ :tickets: 2225
+
+ a CREATE TABLE will put the COLLATE option
+ after CHARSET, which appears to be part of
+ MySQL's arbitrary rules regarding if it will actually
+ work or not.
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2269
+
+ Decode incoming values when retrieving
+ list of index names and the names of columns
+ within those indexes.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2200
+
+ Added ORA-00028 to disconnect codes, use
+ cx_oracle _Error.code to get at the code,.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2220
+
+ repaired the oracle.RAW type which did not
+ generate the correct DDL.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2212
+
+ added CURRENT to reserved word list.
+
+ .. change::
+ :tags: examples
+ :tickets: 2266
+
+ Adjusted dictlike-polymorphic.py example
+ to apply the CAST such that it works on
+ PG, other databases.
+
+.. changelog::
+ :version: 0.6.8
+ :released: Sun Jun 05 2011
+
+ .. change::
+ :tags: orm
+ :tickets: 2144
+
+ Calling query.get() against a column-based entity is
+ invalid, this condition now raises a deprecation warning.
+
+ .. change::
+ :tags: orm
+ :tickets: 2151
+
+ a non_primary mapper will inherit the _identity_class
+ of the primary mapper. This so that a non_primary
+ established against a class that's normally in an
+ inheritance mapping will produce results that are
+ identity-map compatible with that of the primary
+ mapper
+
+ .. change::
+ :tags: orm
+ :tickets: 2148
+
+ Backported 0.7's identity map implementation, which
+ does not use a mutex around removal. This as some users
+ were still getting deadlocks despite the adjustments
+ in 0.6.7; the 0.7 approach that doesn't use a mutex
+ does not appear to produce "dictionary changed size"
+ issues, the original rationale for the mutex.
+
+ .. change::
+ :tags: orm
+ :tickets: 2163
+
+ Fixed the error message emitted for "can't
+ execute syncrule for destination column 'q';
+ mapper 'X' does not map this column" to
+ reference the correct mapper. .
+
+ .. change::
+ :tags: orm
+ :tickets: 2149
+
+ Fixed bug where determination of "self referential"
+ relationship would fail with no workaround
+ for joined-inh subclass related to itself,
+ or joined-inh subclass related to a subclass
+ of that with no cols in the sub-sub class
+ in the join condition.
+
+ .. change::
+ :tags: orm
+ :tickets: 2153
+
+ mapper() will ignore non-configured foreign keys
+ to unrelated tables when determining inherit
+ condition between parent and child class.
+ This is equivalent to behavior already
+ applied to declarative. Note that 0.7 has a
+ more comprehensive solution to this, altering
+ how join() itself determines an FK error.
+
+ .. change::
+ :tags: orm
+ :tickets: 2171
+
+ Fixed bug whereby mapper mapped to an anonymous
+ alias would fail if logging were used, due to
+ unescaped % sign in the alias name.
+
+ .. change::
+ :tags: orm
+ :tickets: 2170
+
+ Modify the text of the message which occurs
+ when the "identity" key isn't detected on
+ flush, to include the common cause that
+ the Column isn't set up to detect
+ auto-increment correctly;.
+
+ .. change::
+ :tags: orm
+ :tickets: 2182
+
+ Fixed bug where transaction-level "deleted"
+ collection wouldn't be cleared of expunged
+ states, raising an error if they later
+ became transient.
+
+ .. change::
+ :tags: sql
+ :tickets: 2147
+
+ Fixed bug whereby if FetchedValue was passed
+ to column server_onupdate, it would not
+ have its parent "column" assigned, added
+ test coverage for all column default assignment
+ patterns.
+
+ .. change::
+ :tags: sql
+ :tickets: 2167
+
+ Fixed bug whereby nesting a label of a select()
+ with another label in it would produce incorrect
+ exported columns. Among other things this would
+ break an ORM column_property() mapping against
+ another column_property(). .
+
+ .. change::
+ :tags: engine
+ :tickets: 2178
+
+ Adjusted the __contains__() method of
+ a RowProxy result row such that no exception
+ throw is generated internally;
+ NoSuchColumnError() also will generate its
+ message regardless of whether or not the column
+ construct can be coerced to a string..
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2141
+
+ Fixed bug affecting PG 9 whereby index reflection
+ would fail if against a column whose name
+ had changed. .
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2175
+
+ Some unit test fixes regarding numeric arrays,
+ MATCH operator. A potential floating-point
+ inaccuracy issue was fixed, and certain tests
+ of the MATCH operator only execute within an
+ EN-oriented locale for now. .
+
+ .. change::
+ :tags: mssql
+ :tickets: 2169
+
+ Fixed bug in MSSQL dialect whereby the aliasing
+ applied to a schema-qualified table would leak
+ into enclosing select statements.
+
+ .. change::
+ :tags: mssql
+ :tickets: 2159
+
+ Fixed bug whereby DATETIME2 type would fail on
+ the "adapt" step when used in result sets or
+ bound parameters. This issue is not in 0.7.
+
+.. changelog::
+ :version: 0.6.7
+ :released: Wed Apr 13 2011
+
+ .. change::
+ :tags: orm
+ :tickets: 2087
+
+ Tightened the iterate vs. remove mutex around the
+ identity map iteration, attempting to reduce the
+ chance of an (extremely rare) reentrant gc operation
+ causing a deadlock. Might remove the mutex in
+ 0.7.
+
+ .. change::
+ :tags: orm
+ :tickets: 2030
+
+ Added a `name` argument to `Query.subquery()`, to allow
+ a fixed name to be assigned to the alias object.
+
+ .. change::
+ :tags: orm
+ :tickets: 2019
+
+ A warning is emitted when a joined-table inheriting mapper
+ has no primary keys on the locally mapped table
+ (but has pks on the superclass table).
+
+ .. change::
+ :tags: orm
+ :tickets: 2038
+
+ Fixed bug where "middle" class in a polymorphic hierarchy
+ would have no 'polymorphic_on' column if it didn't also
+ specify a 'polymorphic_identity', leading to strange
+ errors upon refresh, wrong class loaded when querying
+ from that target. Also emits the correct WHERE criterion
+ when using single table inheritance.
+
+ .. change::
+ :tags: orm
+ :tickets: 1995
+
+ Fixed bug where a column with a SQL or server side default
+ that was excluded from a mapping with include_properties
+ or exclude_properties would result in UnmappedColumnError.
+
+ .. change::
+ :tags: orm
+ :tickets: 2046
+
+ A warning is emitted in the unusual case that an
+ append or similar event on a collection occurs after
+ the parent object has been dereferenced, which
+ prevents the parent from being marked as "dirty"
+ in the session. This will be an exception in 0.7.
+
+ .. change::
+ :tags: orm
+ :tickets: 2098
+
+ Fixed bug in query.options() whereby a path
+ applied to a lazyload using string keys could
+ overlap a same named attribute on the wrong
+ entity. Note 0.7 has an updated version of this
+ fix.
+
+ .. change::
+ :tags: orm
+ :tickets: 2063
+
+ Reworded the exception raised when a flush
+ is attempted of a subclass that is not polymorphic
+ against the supertype.
+
+ .. change::
+ :tags: orm
+ :tickets: 2123
+
+ Some fixes to the state handling regarding
+ backrefs, typically when autoflush=False, where
+ the back-referenced collection wouldn't
+ properly handle add/removes with no net
+ change. Thanks to Richard Murri for the
+ test case + patch.
+
+ .. change::
+ :tags: orm
+ :tickets: 2130
+
+ a "having" clause would be copied from the
+ inside to the outside query if from_self()
+ were used..
+
+ .. change::
+ :tags: sql
+ :tickets: 2028
+
+ Column.copy(), as used in table.tometadata(), copies the
+ 'doc' attribute.
+
+ .. change::
+ :tags: sql
+ :tickets: 2023
+
+ Added some defs to the resultproxy.c extension so that
+ the extension compiles and runs on Python 2.4.
+
+ .. change::
+ :tags: sql
+ :tickets: 2042
+
+ The compiler extension now supports overriding the default
+ compilation of expression._BindParamClause including that
+ the auto-generated binds within the VALUES/SET clause
+ of an insert()/update() statement will also use the new
+ compilation rules.
+
+ .. change::
+ :tags: sql
+ :tickets: 2089
+
+ Added accessors to ResultProxy "returns_rows", "is_insert"
+
+ .. change::
+ :tags: sql
+ :tickets: 2116
+
+ The limit/offset keywords to select() as well
+ as the value passed to select.limit()/offset()
+ will be coerced to integer.
+
+ .. change::
+ :tags: engine
+ :tickets: 2102
+
+ Fixed bug in QueuePool, SingletonThreadPool whereby
+ connections that were discarded via overflow or periodic
+ cleanup() were not explicitly closed, leaving garbage
+ collection to the task instead. This generally only
+ affects non-reference-counting backends like Jython
+ and Pypy. Thanks to Jaimy Azle for spotting
+ this.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 2115
+
+ Fixed bug where reflection of foreign key
+ created as "REFERENCES <tablename>" without
+ col name would fail.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1083
+
+ When explicit sequence execution derives the name
+ of the auto-generated sequence of a SERIAL column,
+ which currently only occurs if implicit_returning=False,
+ now accommodates if the table + column name is greater
+ than 63 characters using the same logic Postgresql uses.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2044
+
+ Added an additional libpq message to the list of "disconnect"
+ exceptions, "could not receive data from server"
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2092
+
+ Added RESERVED_WORDS for postgresql dialect.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2073
+
+ Fixed the BIT type to allow a "length" parameter, "varying"
+ parameter. Reflection also fixed.
+
+ .. change::
+ :tags: informix
+ :tickets: 2092
+
+ Added RESERVED_WORDS informix dialect.
+
+ .. change::
+ :tags: mssql
+ :tickets: 2071
+
+ Rewrote the query used to get the definition of a view,
+ typically when using the Inspector interface, to
+ use sys.sql_modules instead of the information schema,
+ thereby allowing views definitions longer than 4000
+ characters to be fully returned.
+
+ .. change::
+ :tags: mysql
+ :tickets: 2047
+
+ oursql dialect accepts the same "ssl" arguments in
+ create_engine() as that of MySQLdb.
+
+ .. change::
+ :tags: firebird
+ :tickets: 2083
+
+ The "implicit_returning" flag on create_engine() is
+ honored if set to False.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2100
+
+ Using column names that would require quotes
+ for the column itself or for a name-generated
+ bind parameter, such as names with special
+ characters, underscores, non-ascii characters,
+ now properly translate bind parameter keys when
+ talking to cx_oracle.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2116
+
+ Oracle dialect adds use_binds_for_limits=False
+ create_engine() flag, will render the LIMIT/OFFSET
+ values inline instead of as binds, reported to
+ modify the execution plan used by Oracle.
+
+ .. change::
+ :tags: ext
+ :tickets: 2090
+
+ The horizontal_shard ShardedSession class accepts the common
+ Session argument "query_cls" as a constructor argument,
+ to enable further subclassing of ShardedQuery.
+
+ .. change::
+ :tags: declarative
+ :tickets: 2050
+
+ Added an explicit check for the case that the name
+ 'metadata' is used for a column attribute on a
+ declarative class.
+
+ .. change::
+ :tags: declarative
+ :tickets: 2061
+
+ Fix error message referencing old @classproperty
+ name to reference @declared_attr
+
+ .. change::
+ :tags: declarative
+ :tickets: 2091
+
+ Arguments in __mapper_args__ that aren't "hashable"
+ aren't mistaken for always-hashable, possibly-column
+ arguments.
+
+ .. change::
+ :tags: documentation
+ :tickets: 2029
+
+ Documented SQLite DATE/TIME/DATETIME types.
+
+ .. change::
+ :tags: examples
+ :tickets: 2090
+
+ The Beaker caching example allows a "query_cls" argument
+ to the query_callable() function.
+
+.. changelog::
+ :version: 0.6.6
+ :released: Sat Jan 08 2011
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug whereby a non-"mutable" attribute modified event
+ which occurred on an object that was clean except for
+ preceding mutable attribute changes would fail to strongly
+ reference itself in the identity map. This would cause the
+ object to be garbage collected, losing track of any changes
+ that weren't previously saved in the "mutable changes"
+ dictionary.
+
+ .. change::
+ :tags: orm
+ :tickets: 2013
+
+ Fixed bug whereby "passive_deletes='all'" wasn't passing
+ the correct symbols to lazy loaders during flush, thereby
+ causing an unwarranted load.
+
+ .. change::
+ :tags: orm
+ :tickets: 1997
+
+ Fixed bug which prevented composite mapped
+ attributes from being used on a mapped select statement.. Note the workings of composite are slated to
+ change significantly in 0.7.
+
+ .. change::
+ :tags: orm
+ :tickets: 1976
+
+ active_history flag also added to composite().
+ The flag has no effect in 0.6, but is instead
+ a placeholder flag for forwards compatibility,
+ as it applies in 0.7 for composites.
+
+ .. change::
+ :tags: orm
+ :tickets: 2002
+
+ Fixed uow bug whereby expired objects passed to
+ Session.delete() would not have unloaded references
+ or collections taken into account when deleting
+ objects, despite passive_deletes remaining at
+ its default of False.
+
+ .. change::
+ :tags: orm
+ :tickets: 1987
+
+ A warning is emitted when version_id_col is specified
+ on an inheriting mapper when the inherited mapper
+ already has one, if those column expressions are not
+ the same.
+
+ .. change::
+ :tags: orm
+ :tickets: 1954
+
+ "innerjoin" flag doesn't take effect along the chain
+ of joinedload() joins if a previous join in that chain
+ is an outer join, thus allowing primary rows without
+ a referenced child row to be correctly returned
+ in results.
+
+ .. change::
+ :tags: orm
+ :tickets: 1964
+
+ Fixed bug regarding "subqueryload" strategy whereby
+ strategy would fail if the entity was an aliased()
+ construct.
+
+ .. change::
+ :tags: orm
+ :tickets: 2014
+
+ Fixed bug regarding "subqueryload" strategy whereby
+ the join would fail if using a multi-level load
+ of the form from A->joined-subclass->C
+
+ .. change::
+ :tags: orm
+ :tickets: 1968
+
+ Fixed indexing of Query objects by -1. It was erroneously
+ transformed to the empty slice -1:0 that resulted in
+ IndexError.
+
+ .. change::
+ :tags: orm
+ :tickets: 1971
+
+ The mapper argument "primary_key" can be passed as a
+ single column as well as a list or tuple.
+ The documentation examples that illustrated it as a
+ scalar value have been changed to lists.
+
+ .. change::
+ :tags: orm
+ :tickets: 1961
+
+ Added active_history flag to relationship()
+ and column_property(), forces attribute events to
+ always load the "old" value, so that it's available to
+ attributes.get_history().
+
+ .. change::
+ :tags: orm
+ :tickets: 1977
+
+ Query.get() will raise if the number of params
+ in a composite key is too large, as well as too
+ small.
+
+ .. change::
+ :tags: orm
+ :tickets: 1992
+
+ Backport of "optimized get" fix from 0.7,
+ improves the generation of joined-inheritance
+ "load expired row" behavior.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ A little more verbiage to the "primaryjoin" error,
+ in an unusual condition that the join condition
+ "works" for viewonly but doesn't work for non-viewonly,
+ and foreign_keys wasn't used - adds "foreign_keys" to
+ the suggestion. Also add "foreign_keys" to the
+ suggestion for the generic "direction" error.
+
+ .. change::
+ :tags: sql
+ :tickets: 1984
+
+ Fixed operator precedence rules for multiple
+ chains of a single non-associative operator.
+ I.e. "x - (y - z)" will compile as "x - (y - z)"
+ and not "x - y - z". Also works with labels,
+ i.e. "x - (y - z).label('foo')"
+
+ .. change::
+ :tags: sql
+ :tickets: 1967
+
+ The 'info' attribute of Column is copied during
+ Column.copy(), i.e. as occurs when using columns
+ in declarative mixins.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added a bind processor for booleans which coerces
+ to int, for DBAPIs such as pymssql that naively call
+ str() on values.
+
+ .. change::
+ :tags: sql
+ :tickets: 2000
+
+ CheckConstraint will copy its 'initially', 'deferrable',
+ and '_create_rule' attributes within a copy()/tometadata()
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ The "unicode warning" against non-unicode bind data
+ is now raised only when the
+ Unicode type is used explictly; not when
+ convert_unicode=True is used on the engine
+ or String type.
+
+ .. change::
+ :tags: engine
+ :tickets: 1978
+
+ Fixed memory leak in C version of Decimal result
+ processor.
+
+ .. change::
+ :tags: engine
+ :tickets: 1871
+
+ Implemented sequence check capability for the C
+ version of RowProxy, as well as 2.7 style
+ "collections.Sequence" registration for RowProxy.
+
+ .. change::
+ :tags: engine
+ :tickets: 1998
+
+ Threadlocal engine methods rollback(), commit(),
+ prepare() won't raise if no transaction is in progress;
+ this was a regression introduced in 0.6.
+
+ .. change::
+ :tags: engine
+ :tickets: 2004
+
+ Threadlocal engine returns itself upon begin(),
+ begin_nested(); engine then implements contextmanager
+ methods to allow the "with" statement.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1984
+
+ Single element tuple expressions inside an IN clause
+ parenthesize correctly, also from
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1955
+
+ Ensured every numeric, float, int code, scalar + array,
+ are recognized by psycopg2 and pg8000's "numeric"
+ base type.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1956
+
+ Added as_uuid=True flag to the UUID type, will receive
+ and return values as Python UUID() objects rather than
+ strings. Currently, the UUID type is only known to
+ work with psycopg2.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1989
+
+ Fixed bug whereby KeyError would occur with non-ENUM
+ supported PG versions after a pool dispose+recreate
+ would occur.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1960
+
+ Fixed error handling for Jython + zxjdbc, such that
+ has_table() property works again. Regression from
+ 0.6.3 (we don't have a Jython buildbot, sorry)
+
+ .. change::
+ :tags: sqlite
+ :tickets: 1851
+
+ The REFERENCES clause in a CREATE TABLE that includes
+ a remote schema to another table with the same schema
+ name now renders the remote name without
+ the schema clause, as required by SQLite.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ On the same theme, the REFERENCES clause in a CREATE TABLE
+ that includes a remote schema to a *different* schema
+ than that of the parent table doesn't render at all,
+ as cross-schema references do not appear to be supported.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1770
+
+ The rewrite of index reflection in was
+ unfortunately not tested correctly, and returned incorrect
+ results. This regression is now fixed.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1953
+
+ The cx_oracle "decimal detection" logic, which takes place
+ for for result set columns with ambiguous numeric characteristics,
+ now uses the decimal point character determined by the locale/
+ NLS_LANG setting, using an on-first-connect detection of
+ this character. cx_oracle 5.0.3 or greater is also required
+ when using a non-period-decimal-point NLS_LANG setting..
+
+ .. change::
+ :tags: firebird
+ :tickets: 2012
+
+ Firebird numeric type now checks for Decimal explicitly,
+ lets float() pass right through, thereby allowing
+ special values such as float('inf').
+
+ .. change::
+ :tags: declarative
+ :tickets: 1972
+
+ An error is raised if __table_args__ is not in tuple
+ or dict format, and is not None.
+
+ .. change::
+ :tags: sqlsoup
+ :tickets: 1975
+
+ Added "map_to()" method to SqlSoup, which is a "master"
+ method which accepts explicit arguments for each aspect of
+ the selectable and mapping, including a base class per
+ mapping.
+
+ .. change::
+ :tags: sqlsoup
+ :tickets:
+
+ Mapped selectables used with the map(), with_labels(),
+ join() methods no longer put the given argument into the
+ internal "cache" dictionary. Particularly since the
+ join() and select() objects are created in the method
+ itself this was pretty much a pure memory leaking behavior.
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ The versioning example now supports detection of changes
+ in an associated relationship().
+
+.. changelog::
+ :version: 0.6.5
+ :released: Sun Oct 24 2010
+
+ .. change::
+ :tags: orm
+ :tickets: 1914
+
+ Added a new "lazyload" option "immediateload".
+ Issues the usual "lazy" load operation automatically
+ as the object is populated. The use case
+ here is when loading objects to be placed in
+ an offline cache, or otherwise used after
+ the session isn't available, and straight 'select'
+ loading, not 'joined' or 'subquery', is desired.
+
+ .. change::
+ :tags: orm
+ :tickets: 1920
+
+ New Query methods: query.label(name), query.as_scalar(),
+ return the query's statement as a scalar subquery
+ with /without label;
+ query.with_entities(*ent), replaces the SELECT list of
+ the query with new entities.
+ Roughly equivalent to a generative form of query.values()
+ which accepts mapped entities as well as column
+ expressions.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed recursion bug which could occur when moving
+ an object from one reference to another, with
+ backrefs involved, where the initiating parent
+ was a subclass (with its own mapper) of the
+ previous parent.
+
+ .. change::
+ :tags: orm
+ :tickets: 1918
+
+ Fixed a regression in 0.6.4 which occurred if you
+ passed an empty list to "include_properties" on
+ mapper()
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed labeling bug in Query whereby the NamedTuple
+ would mis-apply labels if any of the column
+ expressions were un-labeled.
+
+ .. change::
+ :tags: orm
+ :tickets: 1925
+
+ Patched a case where query.join() would adapt the
+ right side to the right side of the left's join
+ inappropriately
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.select_from() has been beefed up to help
+ ensure that a subsequent call to query.join()
+ will use the select_from() entity, assuming it's
+ a mapped entity and not a plain selectable,
+ as the default "left" side, not the first entity
+ in the Query object's list of entities.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The exception raised by Session when it is used
+ subsequent to a subtransaction rollback (which is what
+ happens when a flush fails in autocommit=False mode) has
+ now been reworded (this is the "inactive due to a
+ rollback in a subtransaction" message). In particular,
+ if the rollback was due to an exception during flush(),
+ the message states this is the case, and reiterates the
+ string form of the original exception that occurred
+ during flush. If the session is closed due to explicit
+ usage of subtransactions (not very common), the message
+ just states this is the case.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The exception raised by Mapper when repeated requests to
+ its initialization are made after initialization already
+ failed no longer assumes the "hasattr" case, since
+ there's other scenarios in which this message gets
+ emitted, and the message also does not compound onto
+ itself multiple times - you get the same message for
+ each attempt at usage. The misnomer "compiles" is being
+ traded out for "initialize".
+
+ .. change::
+ :tags: orm
+ :tickets: 1935
+
+ Fixed bug in query.update() where 'evaluate' or 'fetch'
+ expiration would fail if the column expression key was
+ a class attribute with a different keyname as the
+ actual column name.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added an assertion during flush which ensures
+ that no NULL-holding identity keys were generated
+ on "newly persistent" objects.
+ This can occur when user defined code inadvertently
+ triggers flushes on not-fully-loaded objects.
+
+ .. change::
+ :tags: orm
+ :tickets: 1910
+
+ lazy loads for relationship attributes now use
+ the current state, not the "committed" state,
+ of foreign and primary key attributes
+ when issuing SQL, if a flush is not in process.
+ Previously, only the database-committed state would
+ be used. In particular, this would cause a many-to-one
+ get()-on-lazyload operation to fail, as autoflush
+ is not triggered on these loads when the attributes are
+ determined and the "committed" state may not be
+ available.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ A new flag on relationship(), load_on_pending, allows
+ the lazy loader to fire off on pending objects without a
+ flush taking place, as well as a transient object that's
+ been manually "attached" to the session. Note that this
+ flag blocks attribute events from taking place when an
+ object is loaded, so backrefs aren't available until
+ after a flush. The flag is only intended for very
+ specific use cases.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Another new flag on relationship(), cascade_backrefs,
+ disables the "save-update" cascade when the event was
+ initiated on the "reverse" side of a bidirectional
+ relationship. This is a cleaner behavior so that
+ many-to-ones can be set on a transient object without
+ it getting sucked into the child object's session,
+ while still allowing the forward collection to
+ cascade. We *might* default this to False in 0.7.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Slight improvement to the behavior of
+ "passive_updates=False" when placed only on the
+ many-to-one side of a relationship; documentation has
+ been clarified that passive_updates=False should really
+ be on the one-to-many side.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Placing passive_deletes=True on a many-to-one emits
+ a warning, since you probably intended to put it on
+ the one-to-many side.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug that would prevent "subqueryload" from
+ working correctly with single table inheritance
+ for a relationship from a subclass - the "where
+ type in (x, y, z)" only gets placed on the inside,
+ instead of repeatedly.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ When using from_self() with single table inheritance,
+ the "where type in (x, y, z)" is placed on the outside
+ of the query only, instead of repeatedly. May make
+ some more adjustments to this.
+
+ .. change::
+ :tags: orm
+ :tickets: 1924
+
+ scoped_session emits a warning when configure() is
+ called if a Session is already present (checks only the
+ current thread)
+
+ .. change::
+ :tags: orm
+ :tickets: 1932
+
+ reworked the internals of mapper.cascade_iterator() to
+ cut down method calls by about 9% in some circumstances.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed bug in TypeDecorator whereby the dialect-specific
+ type was getting pulled in to generate the DDL for a
+ given type, which didn't always return the correct result.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ TypeDecorator can now have a fully constructed type
+ specified as its "impl", in addition to a type class.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ TypeDecorator will now place itself as the resulting
+ type for a binary expression where the type coercion
+ rules would normally return its impl type - previously,
+ a copy of the impl type would be returned which would
+ have the TypeDecorator embedded into it as the "dialect"
+ impl, this was probably an unintentional way of achieving
+ the desired effect.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ TypeDecorator.load_dialect_impl() returns "self.impl" by
+ default, i.e. not the dialect implementation type of
+ "self.impl". This to support compilation correctly.
+ Behavior can be user-overridden in exactly the same way
+ as before to the same effect.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added type_coerce(expr, type_) expression element.
+ Treats the given expression as the given type when evaluating
+ expressions and processing result rows, but does not
+ affect the generation of SQL, other than an anonymous
+ label.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Table.tometadata() now copies Index objects associated
+ with the Table as well.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Table.tometadata() issues a warning if the given Table
+ is already present in the target MetaData - the existing
+ Table object is returned.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ An informative error message is raised if a Column
+ which has not yet been assigned a name, i.e. as in
+ declarative, is used in a context where it is
+ exported to the columns collection of an enclosing
+ select() construct, or if any construct involving
+ that column is compiled before its name is
+ assigned.
+
+ .. change::
+ :tags: sql
+ :tickets: 1862
+
+ as_scalar(), label() can be called on a selectable
+ which contains a Column that is not yet named.
+
+ .. change::
+ :tags: sql
+ :tickets: 1907
+
+ Fixed recursion overflow which could occur when operating
+ with two expressions both of type "NullType", but
+ not the singleton NULLTYPE instance.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1922
+
+ @classproperty (soon/now @declared_attr) takes effect for
+ __mapper_args__, __table_args__, __tablename__ on
+ a base class that is not a mixin, as well as mixins.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1915
+
+ @classproperty 's official name/location for usage
+ with declarative is sqlalchemy.ext.declarative.declared_attr.
+ Same thing, but moving there since it is more of a
+ "marker" that's specific to declararative,
+ not just an attribute technique.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1931, 1930
+
+ Fixed bug whereby columns on a mixin wouldn't propagate
+ correctly to a single-table, or joined-table,
+ inheritance scheme where the attribute name is
+ different than that of the column.,.
+
+ .. change::
+ :tags: declarative
+ :tickets:
+
+ A mixin can now specify a column that overrides
+ a column of the same name associated with a superclass.
+ Thanks to Oystein Haaland.
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ Fixed a regression in 0.6.4 whereby the change that
+ allowed cursor errors to be raised consistently broke
+ the result.lastrowid accessor. Test coverage has
+ been added for result.lastrowid. Note that lastrowid
+ is only supported by Pysqlite and some MySQL drivers,
+ so isn't super-useful in the general case.
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ the logging message emitted by the engine when
+ a connection is first used is now "BEGIN (implicit)"
+ to emphasize that DBAPI has no explicit begin().
+
+ .. change::
+ :tags: engine
+ :tickets: 1936
+
+ added "views=True" option to metadata.reflect(),
+ will add the list of available views to those
+ being reflected.
+
+ .. change::
+ :tags: engine
+ :tickets: 1899
+
+ engine_from_config() now accepts 'debug' for
+ 'echo', 'echo_pool', 'force' for 'convert_unicode',
+ boolean values for 'use_native_unicode'.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ Added "as_tuple" flag to ARRAY type, returns results
+ as tuples instead of lists to allow hashing.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1933
+
+ Fixed bug which prevented "domain" built from a
+ custom type such as "enum" from being reflected.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1940
+
+ Fixed bug involving reflection of CURRENT_TIMESTAMP
+ default used with ON UPDATE clause, thanks to
+ Taavi Burns
+
+ .. change::
+ :tags: oracle
+ :tickets: 1878
+
+ The implicit_retunring argument to create_engine()
+ is now honored regardless of detected version of
+ Oracle. Previously, the flag would be forced
+ to False if server version info was < 10.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1946
+
+ Fixed reflection bug which did not properly handle
+ reflection of unknown types.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1943
+
+ Fixed bug where aliasing of tables with "schema" would
+ fail to compile properly.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1770
+
+ Rewrote the reflection of indexes to use sys.
+ catalogs, so that column names of any configuration
+ (spaces, embedded commas, etc.) can be reflected.
+ Note that reflection of indexes requires SQL
+ Server 2005 or greater.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1952
+
+ mssql+pymssql dialect now honors the "port" portion
+ of the URL instead of discarding it.
+
+ .. change::
+ :tags: informix
+ :tickets: 1906
+
+ *Major* cleanup / modernization of the Informix
+ dialect for 0.6, courtesy Florian Apolloner.
+
+ .. change::
+ :tags: tests
+ :tickets:
+
+ the NoseSQLAlchemyPlugin has been moved to a
+ new package "sqlalchemy_nose" which installs
+ along with "sqlalchemy". This so that the "nosetests"
+ script works as always but also allows the
+ --with-coverage option to turn on coverage before
+ SQLAlchemy modules are imported, allowing coverage
+ to work correctly.
+
+ .. change::
+ :tags: misc
+ :tickets: 1890
+
+ CircularDependencyError now has .cycles and .edges
+ members, which are the set of elements involved in
+ one or more cycles, and the set of edges as 2-tuples.
+
+.. changelog::
+ :version: 0.6.4
+ :released: Tue Sep 07 2010
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The name ConcurrentModificationError has been
+ changed to StaleDataError, and descriptive
+ error messages have been revised to reflect
+ exactly what the issue is. Both names will
+ remain available for the forseeable future
+ for schemes that may be specifying
+ ConcurrentModificationError in an "except:"
+ clause.
+
+ .. change::
+ :tags: orm
+ :tickets: 1891
+
+ Added a mutex to the identity map which mutexes
+ remove operations against iteration methods,
+ which now pre-buffer before returning an
+ iterable. This because asyncrhonous gc
+ can remove items via the gc thread at any time.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The Session class is now present in sqlalchemy.orm.*.
+ We're moving away from the usage of create_session(),
+ which has non-standard defaults, for those situations
+ where a one-step Session constructor is desired. Most
+ users should stick with sessionmaker() for general use,
+ however.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.with_parent() now accepts transient objects
+ and will use the non-persistent values of their pk/fk
+ attributes in order to formulate the criterion.
+ Docs are also clarified as to the purpose of with_parent().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The include_properties and exclude_properties arguments
+ to mapper() now accept Column objects as members in
+ addition to strings. This so that same-named Column
+ objects, such as those within a join(), can be
+ disambiguated.
+
+ .. change::
+ :tags: orm
+ :tickets: 1896
+
+ A warning is now emitted if a mapper is created against a
+ join or other single selectable that includes multiple
+ columns with the same name in its .c. collection,
+ and those columns aren't explictly named as part of
+ the same or separate attributes (or excluded).
+ In 0.7 this warning will be an exception. Note that
+ this warning is not emitted when the combination occurs
+ as a result of inheritance, so that attributes
+ still allow being overridden naturally.. In 0.7 this will be improved further.
+
+ .. change::
+ :tags: orm
+ :tickets: 1896
+
+ The primary_key argument to mapper() can now specify
+ a series of columns that are only a subset of
+ the calculated "primary key" columns of the mapped
+ selectable, without an error being raised. This
+ helps for situations where a selectable's effective
+ primary key is simpler than the number of columns
+ in the selectable that are actually marked as
+ "primary_key", such as a join against two
+ tables on their primary key columns.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ An object that's been deleted now gets a flag
+ 'deleted', which prohibits the object from
+ being re-add()ed to the session, as previously
+ the object would live in the identity map
+ silently until its attributes were accessed.
+ The make_transient() function now resets this
+ flag along with the "key" flag.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ make_transient() can be safely called on an
+ already transient instance.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ a warning is emitted in mapper() if the polymorphic_on
+ column is not present either in direct or derived
+ form in the mapped selectable or in the
+ with_polymorphic selectable, instead of silently
+ ignoring it. Look for this to become an
+ exception in 0.7.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Another pass through the series of error messages
+ emitted when relationship() is configured with
+ ambiguous arguments. The "foreign_keys"
+ setting is no longer mentioned, as it is almost
+ never needed and it is preferable users set up
+ correct ForeignKey metadata, which is now the
+ recommendation. If 'foreign_keys'
+ is used and is incorrect, the message suggests
+ the attribute is probably unnecessary. Docs
+ for the attribute are beefed up. This
+ because all confused relationship() users on the
+ ML appear to be attempting to use foreign_keys
+ due to the message, which only confuses them
+ further since Table metadata is much clearer.
+
+ .. change::
+ :tags: orm
+ :tickets: 1877
+
+ If the "secondary" table has no ForeignKey metadata
+ and no foreign_keys is set, even though the
+ user is passing screwed up information, it is assumed
+ that primary/secondaryjoin expressions should
+ consider only and all cols in "secondary" to be
+ foreign. It's not possible with "secondary" for
+ the foreign keys to be elsewhere in any case.
+ A warning is now emitted instead of an error,
+ and the mapping succeeds.
+
+ .. change::
+ :tags: orm
+ :tickets: 1856
+
+ Moving an o2m object from one collection to
+ another, or vice versa changing the referenced
+ object by an m2o, where the foreign key is also a
+ member of the primary key, will now be more
+ carefully checked during flush if the change in
+ value of the foreign key on the "many" side is the
+ result of a change in the primary key of the "one"
+ side, or if the "one" is just a different object.
+ In one case, a cascade-capable DB would have
+ cascaded the value already and we need to look at
+ the "new" PK value to do an UPDATE, in the other we
+ need to continue looking at the "old". We now look
+ at the "old", assuming passive_updates=True,
+ unless we know it was a PK switch that
+ triggered the change.
+
+ .. change::
+ :tags: orm
+ :tickets: 1857
+
+ The value of version_id_col can be changed
+ manually, and this will result in an UPDATE
+ of the row. Versioned UPDATEs and DELETEs
+ now use the "committed" value of the
+ version_id_col in the WHERE clause and
+ not the pending changed value. The
+ version generator is also bypassed if
+ manual changes are present on the attribute.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Repaired the usage of merge() when used with
+ concrete inheriting mappers. Such mappers frequently
+ have so-called "concrete" attributes, which are
+ subclass attributes that "disable" propagation from
+ the parent - these needed to allow a merge()
+ operation to pass through without effect.
+
+ .. change::
+ :tags: orm
+ :tickets: 1863
+
+ Specifying a non-column based argument
+ for column_mapped_collection, including string,
+ text() etc., will raise an error message that
+ specifically asks for a column element, no longer
+ misleads with incorrect information about
+ text() or literal().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Similarly, for relationship(), foreign_keys,
+ remote_side, order_by - all column-based
+ expressions are enforced - lists of strings
+ are explicitly disallowed since this is a
+ very common error
+
+ .. change::
+ :tags: orm
+ :tickets: 1864
+
+ Dynamic attributes don't support collection
+ population - added an assertion for when
+ set_committed_value() is called, as well as
+ when joinedload() or subqueryload() options
+ are applied to a dynamic attribute, instead
+ of failure / silent failure.
+
+ .. change::
+ :tags: orm
+ :tickets: 1852
+
+ Fixed bug whereby generating a Query derived
+ from one which had the same column repeated
+ with different label names, typically
+ in some UNION situations, would fail to
+ propagate the inner columns completely to
+ the outer query.
+
+ .. change::
+ :tags: orm
+ :tickets: 1881
+
+ object_session() raises the proper
+ UnmappedInstanceError when presented with an
+ unmapped instance.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Applied further memoizations to calculated Mapper
+ properties, with significant (~90%) runtime mapper.py
+ call count reduction in heavily polymorphic mapping
+ configurations.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ mapper _get_col_to_prop private method used
+ by the versioning example is deprecated;
+ now use mapper.get_property_by_column() which
+ will remain the public method for this.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the versioning example works correctly now
+ if versioning on a col that was formerly
+ NULL.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Calling execute() on an alias() construct is pending
+ deprecation for 0.7, as it is not itself an
+ "executable" construct. It currently "proxies" its
+ inner element and is conditionally "executable" but
+ this is not the kind of ambiguity we like these days.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The execute() and scalar() methods of ClauseElement
+ are now moved appropriately to the Executable
+ subclass. ClauseElement.execute()/ scalar() are still
+ present and are pending deprecation in 0.7, but note
+ these would always raise an error anyway if you were
+ not an Executable (unless you were an alias(), see
+ previous note).
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added basic math expression coercion for
+ Numeric->Integer,
+ so that resulting type is Numeric regardless
+ of the direction of the expression.
+
+ .. change::
+ :tags: sql
+ :tickets: 1855
+
+ Changed the scheme used to generate truncated
+ "auto" index names when using the "index=True"
+ flag on Column. The truncation only takes
+ place with the auto-generated name, not one
+ that is user-defined (an error would be
+ raised instead), and the truncation scheme
+ itself is now based on a fragment of an md5
+ hash of the identifier name, so that multiple
+ indexes on columns with similar names still
+ have unique names.
+
+ .. change::
+ :tags: sql
+ :tickets: 1412
+
+ The generated index name also is based on
+ a "max index name length" attribute which is
+ separate from the "max identifier length" -
+ this to appease MySQL who has a max length
+ of 64 for index names, separate from their
+ overall max length of 255.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the text() construct, if placed in a column
+ oriented situation, will at least return NULLTYPE
+ for its type instead of None, allowing it to
+ be used a little more freely for ad-hoc column
+ expressions than before. literal_column()
+ is still the better choice, however.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added full description of parent table/column,
+ target table/column in error message raised when
+ ForeignKey can't resolve target.
+
+ .. change::
+ :tags: sql
+ :tickets: 1865
+
+ Fixed bug whereby replacing composite foreign key
+ columns in a reflected table would cause an attempt
+ to remove the reflected constraint from the table
+ a second time, raising a KeyError.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the _Label construct, i.e. the one that is produced
+ whenever you say somecol.label(), now counts itself
+ in its "proxy_set" unioned with that of it's
+ contained column's proxy set, instead of
+ directly returning that of the contained column.
+ This allows column correspondence
+ operations which depend on the identity of the
+ _Labels themselves to return the correct result
+
+ .. change::
+ :tags: sql
+ :tickets: 1852
+
+ fixes ORM bug.
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ Calling fetchone() or similar on a result that
+ has already been exhausted, has been closed,
+ or is not a result-returning result now
+ raises ResourceClosedError, a subclass of
+ InvalidRequestError, in all cases, regardless
+ of backend. Previously, some DBAPIs would
+ raise ProgrammingError (i.e. pysqlite), others
+ would return None leading to downstream breakages
+ (i.e. MySQL-python).
+
+ .. change::
+ :tags: engine
+ :tickets: 1894
+
+ Fixed bug in Connection whereby if a "disconnect"
+ event occurred in the "initialize" phase of the
+ first connection pool connect, an AttributeError
+ would be raised when the Connection would attempt
+ to invalidate the DBAPI connection.
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ Connection, ResultProxy, as well as Session use
+ ResourceClosedError for all "this
+ connection/transaction/result is closed" types of
+ errors.
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ Connection.invalidate() can be called more than
+ once and subsequent calls do nothing.
+
+ .. change::
+ :tags: declarative
+ :tickets:
+
+ if @classproperty is used with a regular class-bound
+ mapper property attribute, it will be called to get the
+ actual attribute value during initialization. Currently,
+ there's no advantage to using @classproperty on a column
+ or relationship attribute of a declarative class that
+ isn't a mixin - evaluation is at the same time as if
+ @classproperty weren't used. But here we at least allow
+ it to function as expected.
+
+ .. change::
+ :tags: declarative
+ :tickets:
+
+ Fixed bug where "Can't add additional column" message
+ would display the wrong name.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ Fixed the psycopg2 dialect to use its
+ set_isolation_level() method instead of relying
+ upon the base "SET SESSION ISOLATION" command,
+ as psycopg2 resets the isolation level on each new
+ transaction otherwise.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Fixed "default schema" query to work with
+ pymssql backend.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ Fixed bug whereby a column default would fail to
+ reflect if the "default" keyword were lower case.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1879
+
+ Added ROWID type to the Oracle dialect, for those
+ cases where an explicit CAST might be needed.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1867
+
+ Oracle reflection of indexes has been tuned so
+ that indexes which include some or all primary
+ key columns, but not the same set of columns
+ as that of the primary key, are reflected.
+ Indexes which contain the identical columns
+ as that of the primary key are skipped within
+ reflection, as the index in that case is assumed
+ to be the auto-generated primary key index.
+ Previously, any index with PK columns present
+ would be skipped. Thanks to Kent Bower
+ for the patch.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1868
+
+ Oracle now reflects the names of primary key
+ constraints - also thanks to Kent Bower.
+
+ .. change::
+ :tags: informix
+ :tickets: 1904
+
+ Applied patches from to get
+ basic Informix functionality up again. We
+ rely upon end-user testing to ensure that
+ Informix is working to some degree.
+
+ .. change::
+ :tags: documentation
+ :tickets:
+
+ The docs have been reorganized such that the "API
+ Reference" section is gone - all the docstrings from
+ there which were public API are moved into the
+ context of the main doc section that talks about it.
+ Main docs divided into "SQLAlchemy Core" and
+ "SQLAlchemy ORM" sections, mapper/relationship docs
+ have been broken out. Lots of sections rewritten
+ and/or reorganized.
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ The beaker_caching example has been reorgnized
+ such that the Session, cache manager,
+ declarative_base are part of environment, and
+ custom cache code is portable and now within
+ "caching_query.py". This allows the example to
+ be easier to "drop in" to existing projects.
+
+ .. change::
+ :tags: examples
+ :tickets: 1887
+
+ the history_meta versioning recipe sets "unique=False"
+ when copying columns, so that the versioning
+ table handles multiple rows with repeating values.
+
+.. changelog::
+ :version: 0.6.3
+ :released: Thu Jul 15 2010
+
+ .. change::
+ :tags: orm
+ :tickets: 1845
+
+ Removed errant many-to-many load in unitofwork
+ which triggered unnecessarily on expired/unloaded
+ collections. This load now takes place only if
+ passive_updates is False and the parent primary
+ key has changed, or if passive_deletes is False
+ and a delete of the parent has occurred.
+
+ .. change::
+ :tags: orm
+ :tickets: 1853
+
+ Column-entities (i.e. query(Foo.id)) copy their
+ state more fully when queries are derived from
+ themselves + a selectable (i.e. from_self(),
+ union(), etc.), so that join() and such have the
+ correct state to work from.
+
+ .. change::
+ :tags: orm
+ :tickets: 1853
+
+ Fixed bug where Query.join() would fail if
+ querying a non-ORM column then joining without
+ an on clause when a FROM clause is already
+ present, now raises a checked exception the
+ same way it does when the clause is not
+ present.
+
+ .. change::
+ :tags: orm
+ :tickets: 1142
+
+ Improved the check for an "unmapped class",
+ including the case where the superclass is mapped
+ but the subclass is not. Any attempts to access
+ cls._sa_class_manager.mapper now raise
+ UnmappedClassError().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added "column_descriptions" accessor to Query,
+ returns a list of dictionaries containing
+ naming/typing information about the entities
+ the Query will return. Can be helpful for
+ building GUIs on top of ORM queries.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1848
+
+ The _extract_error_code() method now works
+ correctly with each MySQL dialect (
+ MySQL-python, OurSQL, MySQL-Connector-Python,
+ PyODBC). Previously,
+ the reconnect logic would fail for OperationalError
+ conditions, however since MySQLdb and OurSQL
+ have their own reconnect feature, there was no
+ symptom for these drivers here unless one
+ watched the logs.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1840
+
+ More tweaks to cx_oracle Decimal handling.
+ "Ambiguous" numerics with no decimal place
+ are coerced to int at the connection handler
+ level. The advantage here is that ints
+ come back as ints without SQLA type
+ objects being involved and without needless
+ conversion to Decimal first.
+
+ Unfortunately, some exotic subquery cases
+ can even see different types between
+ individual result rows, so the Numeric
+ handler, when instructed to return Decimal,
+ can't take full advantage of "native decimal"
+ mode and must run isinstance() on every value
+ to check if its Decimal already. Reopen of
+
+.. changelog::
+ :version: 0.6.2
+ :released: Tue Jul 06 2010
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.join() will check for a call of the
+ form query.join(target, clause_expression),
+ i.e. missing the tuple, and raise an informative
+ error message that this is the wrong calling form.
+
+ .. change::
+ :tags: orm
+ :tickets: 1824
+
+ Fixed bug regarding flushes on self-referential
+ bi-directional many-to-many relationships, where
+ two objects made to mutually reference each other
+ in one flush would fail to insert a row for both
+ sides. Regression from 0.5.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the post_update feature of relationship() has been
+ reworked architecturally to integrate more closely
+ with the new 0.6 unit of work. The motivation
+ for the change is so that multiple "post update"
+ calls, each affecting different foreign key
+ columns of the same row, are executed in a single
+ UPDATE statement, rather than one UPDATE
+ statement per column per row. Multiple row
+ updates are also batched into executemany()s as
+ possible, while maintaining consistent row ordering.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.statement, Query.subquery(), etc. now transfer
+ the values of bind parameters, i.e. those specified
+ by query.params(), into the resulting SQL expression.
+ Previously the values would not be transferred
+ and bind parameters would come out as None.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Subquery-eager-loading now works with Query objects
+ which include params(), as well as get() Queries.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Can now call make_transient() on an instance that
+ is referenced by parent objects via many-to-one,
+ without the parent's foreign key value getting
+ temporarily set to None - this was a function
+ of the "detect primary key switch" flush handler.
+ It now ignores objects that are no longer
+ in the "persistent" state, and the parent's
+ foreign key identifier is left unaffected.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.order_by() now accepts False, which cancels
+ any existing order_by() state on the Query, allowing
+ subsequent generative methods to be called which do
+ not support ORDER BY. This is not the same as the
+ already existing feature of passing None, which
+ suppresses any existing order_by() settings, including
+ those configured on the mapper. False will make it
+ as though order_by() was never called, while
+ None is an active setting.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ An instance which is moved to "transient", has
+ an incomplete or missing set of primary key
+ attributes, and contains expired attributes, will
+ raise an InvalidRequestError if an expired attribute
+ is accessed, instead of getting a recursion overflow.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The make_transient() function is now in the generated
+ documentation.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ make_transient() removes all "loader" callables from
+ the state being made transient, removing any
+ "expired" state - all unloaded attributes reset back
+ to undefined, None/empty on access.
+
+ .. change::
+ :tags: sql
+ :tickets: 1822
+
+ The warning emitted by the Unicode and String types
+ with convert_unicode=True no longer embeds the actual
+ value passed. This so that the Python warning
+ registry does not continue to grow in size, the warning
+ is emitted once as per the warning filter settings,
+ and large string values don't pollute the output.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed bug that would prevent overridden clause
+ compilation from working for "annotated" expression
+ elements, which are often generated by the ORM.
+
+ .. change::
+ :tags: sql
+ :tickets: 1400
+
+ The argument to "ESCAPE" of a LIKE operator or similar
+ is passed through render_literal_value(), which may
+ implement escaping of backslashes.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed bug in Enum type which blew away native_enum
+ flag when used with TypeDecorators or other adaption
+ scenarios.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Inspector hits bind.connect() when invoked to ensure
+ initialize has been called. the internal name ".conn"
+ is changed to ".bind", since that's what it is.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Modified the internals of "column annotation" such that
+ a custom Column subclass can safely override
+ _constructor to return Column, for the purposes of
+ making "configurational" column classes that aren't
+ involved in proxying, etc.
+
+ .. change::
+ :tags: sql
+ :tickets: 1829
+
+ Column.copy() takes along the "unique" attribute
+ among others, fixes regarding declarative
+ mixins
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1400
+
+ render_literal_value() is overridden which escapes
+ backslashes, currently applies to the ESCAPE clause
+ of LIKE and similar expressions.
+ Ultimately this will have to detect the value of
+ "standard_conforming_strings" for full behavior.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1836
+
+ Won't generate "CREATE TYPE" / "DROP TYPE" if
+ using types.Enum on a PG version prior to 8.3 -
+ the supports_native_enum flag is fully
+ honored.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1826
+
+ MySQL dialect doesn't emit CAST() for MySQL version
+ detected < 4.0.2. This allows the unicode
+ check on connect to proceed.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ MySQL dialect now detects NO_BACKSLASH_ESCAPES sql
+ mode, in addition to ANSI_QUOTES.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1400
+
+ render_literal_value() is overridden which escapes
+ backslashes, currently applies to the ESCAPE clause
+ of LIKE and similar expressions. This behavior
+ is derived from detecting the value of
+ NO_BACKSLASH_ESCAPES.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1819
+
+ Fixed ora-8 compatibility flags such that they
+ don't cache a stale value from before the first
+ database connection actually occurs.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1840
+
+ Oracle's "native decimal" metadata begins to return
+ ambiguous typing information about numerics
+ when columns are embedded in subqueries as well
+ as when ROWNUM is consulted with subqueries, as we
+ do for limit/offset. We've added these ambiguous
+ conditions to the cx_oracle "convert to Decimal()"
+ handler, so that we receive numerics as Decimal
+ in more cases instead of as floats. These are
+ then converted, if requested, into Integer
+ or Float, or otherwise kept as the lossless
+ Decimal.
+
+ .. change::
+ :tags: mssql
+ :tickets: 1825
+
+ If server_version_info is outside the usual
+ range of (8, ), (9, ), (10, ), a warning is emitted
+ which suggests checking that the FreeTDS version
+ configuration is using 7.0 or 8.0, not 4.2.
+
+ .. change::
+ :tags: firebird
+ :tickets: 1823
+
+ Fixed incorrect signature in do_execute(), error
+ introduced in 0.6.1.
+
+ .. change::
+ :tags: firebird
+ :tickets: 1813
+
+ Firebird dialect adds CHAR, VARCHAR types which
+ accept a "charset" flag, to support Firebird
+ "CHARACTER SET" clause.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1805, 1796, 1751
+
+ Added support for @classproperty to provide
+ any kind of schema/mapping construct from a
+ declarative mixin, including columns with foreign
+ keys, relationships, column_property, deferred.
+ This solves all such issues on declarative mixins.
+ An error is raised if any MapperProperty subclass
+ is specified on a mixin without using @classproperty.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1821
+
+ a mixin class can now define a column that matches
+ one which is present on a __table__ defined on a
+ subclass. It cannot, however, define one that is
+ not present in the __table__, and the error message
+ here now works.
+
+ .. change::
+ :tags: extension, compiler
+ :tickets: 1838
+
+ The 'default' compiler is automatically copied over
+ when overriding the compilation of a built in
+ clause construct, so no KeyError is raised if the
+ user-defined compiler is specific to certain
+ backends and compilation for a different backend
+ is invoked.
+
+ .. change::
+ :tags: documentation
+ :tickets: 1820
+
+ Added documentation for the Inspector.
+
+ .. change::
+ :tags: documentation
+ :tickets: 1830
+
+ Fixed @memoized_property and @memoized_instancemethod
+ decorators so that Sphinx documentation picks up
+ these attributes and methods, such as
+ ResultProxy.inserted_primary_key.
+
+.. changelog::
+ :version: 0.6.1
+ :released: Mon May 31 2010
+
+ .. change::
+ :tags: orm
+ :tickets: 1782
+
+ Fixed regression introduced in 0.6.0 involving improper
+ history accounting on mutable attributes.
+
+ .. change::
+ :tags: orm
+ :tickets: 1807
+
+ Fixed regression introduced in 0.6.0 unit of work refactor
+ that broke updates for bi-directional relationship()
+ with post_update=True.
+
+ .. change::
+ :tags: orm
+ :tickets: 1789
+
+ session.merge() will not expire attributes on the returned
+ instance if that instance is "pending".
+
+ .. change::
+ :tags: orm
+ :tickets: 1802
+
+ fixed __setstate__ method of CollectionAdapter to not
+ fail during deserialize where parent InstanceState not
+ yet unserialized.
+
+ .. change::
+ :tags: orm
+ :tickets: 1797
+
+ Added internal warning in case an instance without a
+ full PK happened to be expired and then was asked
+ to refresh.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added more aggressive caching to the mapper's usage of
+ UPDATE, INSERT, and DELETE expressions. Assuming the
+ statement has no per-object SQL expressions attached,
+ the expression objects are cached by the mapper after
+ the first create, and their compiled form is stored
+ persistently in a cache dictionary for the duration of
+ the related Engine. The cache is an LRUCache for the
+ rare case that a mapper receives an extremely
+ high number of different column patterns as UPDATEs.
+
+ .. change::
+ :tags: sql
+ :tickets: 1793
+
+ expr.in_() now accepts a text() construct as the argument.
+ Grouping parenthesis are added automatically, i.e. usage
+ is like `col.in_(text("select id from table"))`.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Columns of _Binary type (i.e. LargeBinary, BLOB, etc.)
+ will coerce a "basestring" on the right side into a
+ _Binary as well so that required DBAPI processing
+ takes place.
+
+ .. change::
+ :tags: sql
+ :tickets: 1801
+
+ Added table.add_is_dependent_on(othertable), allows manual
+ placement of dependency rules between two Table objects
+ for use within create_all(), drop_all(), sorted_tables.
+
+ .. change::
+ :tags: sql
+ :tickets: 1778
+
+ Fixed bug that prevented implicit RETURNING from functioning
+ properly with composite primary key that contained zeroes.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed errant space character when generating ADD CONSTRAINT
+ for a named UNIQUE constraint.
+
+ .. change::
+ :tags: sql
+ :tickets: 1571
+
+ Fixed "table" argument on constructor of ForeginKeyConstraint
+
+ .. change::
+ :tags: sql
+ :tickets: 1786
+
+ Fixed bug in connection pool cursor wrapper whereby if a
+ cursor threw an exception on close(), the logging of the
+ message would fail.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the _make_proxy() method of ColumnClause and Column now use
+ self.__class__ to determine the class of object to be returned
+ instead of hardcoding to ColumnClause/Column, making it slightly
+ easier to produce specific subclasses of these which work in
+ alias/subquery situations.
+
+ .. change::
+ :tags: sql
+ :tickets: 1798
+
+ func.XXX() doesn't inadvertently resolve to non-Function
+ classes (e.g. fixes func.text()).
+
+ .. change::
+ :tags: engines
+ :tickets: 1781
+
+ Fixed building the C extensions on Python 2.4.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Pool classes will reuse the same "pool_logging_name" setting
+ after a dispose() occurs.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Engine gains an "execution_options" argument and
+ update_execution_options() method, which will apply to
+ all connections generated by this engine.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1794
+
+ func.sysdate() emits "SYSDATE()", i.e. with the ending
+ parenthesis, on MySQL.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 1812
+
+ Fixed concatenation of constraints when "PRIMARY KEY"
+ constraint gets moved to column level due to SQLite
+ AUTOINCREMENT keyword being rendered.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1775
+
+ Added a check for cx_oracle versions lower than version 5,
+ in which case the incompatible "output type handler" won't
+ be used. This will impact decimal accuracy and some
+ unicode handling issues.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1790
+
+ Fixed use_ansi=False mode, which was producing broken
+ WHERE clauses in pretty much all cases.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1808
+
+ Re-established support for Oracle 8 with cx_oracle,
+ including that use_ansi is set to False automatically,
+ NVARCHAR2 and NCLOB are not rendered for Unicode,
+ "native unicode" check doesn't fail, cx_oracle
+ "native unicode" mode is disabled, VARCHAR() is emitted
+ with bytes count instead of char count.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1670
+
+ oracle_xe 5 doesn't accept a Python unicode object in
+ its connect string in normal Python 2.x mode - so we coerce
+ to str() directly. non-ascii characters aren't supported
+ in connect strings here since we don't know what encoding
+ we could use.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1815
+
+ FOR UPDATE is emitted in the syntactically correct position
+ when limit/offset is used, i.e. the ROWNUM subquery.
+ However, Oracle can't really handle FOR UPDATE with ORDER BY
+ or with subqueries, so its still not very usable, but at
+ least SQLA gets the SQL past the Oracle parser.
+
+ .. change::
+ :tags: firebird
+ :tickets: 1521
+
+ Added a label to the query used within has_table() and
+ has_sequence() to work with older versions of Firebird
+ that don't provide labels for result columns.
+
+ .. change::
+ :tags: firebird
+ :tickets: 1779
+
+ Added integer coercion to the "type_conv" attribute when
+ passed via query string, so that it is properly interpreted
+ by Kinterbasdb.
+
+ .. change::
+ :tags: firebird
+ :tickets: 1646
+
+ Added 'connection shutdown' to the list of exception strings
+ which indicate a dropped connection.
+
+ .. change::
+ :tags: sqlsoup
+ :tickets: 1783
+
+ the SqlSoup constructor accepts a `base` argument which specifies
+ the base class to use for mapped classes, the default being
+ `object`.
+
+.. changelog::
+ :version: 0.6.0
+ :released: Sun Apr 18 2010
+
+ .. change::
+ :tags: orm
+ :tickets: 1742, 1081
+
+ Unit of work internals have been rewritten. Units of work
+ with large numbers of objects interdependent objects
+ can now be flushed without recursion overflows
+ as there is no longer reliance upon recursive calls. The number of internal structures now stays
+ constant for a particular session state, regardless of
+ how many relationships are present on mappings. The flow
+ of events now corresponds to a linear list of steps,
+ generated by the mappers and relationships based on actual
+ work to be done, filtered through a single topological sort
+ for correct ordering. Flush actions are assembled using
+ far fewer steps and less memory.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Along with the UOW rewrite, this also removes an issue
+ introduced in 0.6beta3 regarding topological cycle detection
+ for units of work with long dependency cycles. We now use
+ an algorithm written by Guido (thanks Guido!).
+
+ .. change::
+ :tags: orm
+ :tickets: 1764
+
+ one-to-many relationships now maintain a list of positive
+ parent-child associations within the flush, preventing
+ previous parents marked as deleted from cascading a
+ delete or NULL foreign key set on those child objects,
+ despite the end-user not removing the child from the old
+ association.
+
+ .. change::
+ :tags: orm
+ :tickets: 1495
+
+ A collection lazy load will switch off default
+ eagerloading on the reverse many-to-one side, since
+ that loading is by definition unnecessary.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session.refresh() now does an equivalent expire()
+ on the given instance first, so that the "refresh-expire"
+ cascade is propagated. Previously, refresh() was
+ not affected in any way by the presence of "refresh-expire"
+ cascade. This is a change in behavior versus that
+ of 0.6beta2, where the "lockmode" flag passed to refresh()
+ would cause a version check to occur. Since the instance
+ is first expired, refresh() always upgrades the object
+ to the most recent version.
+
+ .. change::
+ :tags: orm
+ :tickets: 1754
+
+ The 'refresh-expire' cascade, when reaching a pending object,
+ will expunge the object if the cascade also includes
+ "delete-orphan", or will simply detach it otherwise.
+
+ .. change::
+ :tags: orm
+ :tickets: 1756
+
+ id(obj) is no longer used internally within topological.py,
+ as the sorting functions now require hashable objects
+ only.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The ORM will set the docstring of all generated descriptors
+ to None by default. This can be overridden using 'doc'
+ (or if using Sphinx, attribute docstrings work too).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added kw argument 'doc' to all mapper property callables
+ as well as Column(). Will assemble the string 'doc' as
+ the '__doc__' attribute on the descriptor.
+
+ .. change::
+ :tags: orm
+ :tickets: 1761
+
+ Usage of version_id_col on a backend that supports
+ cursor.rowcount for execute() but not executemany() now works
+ when a delete is issued (already worked for saves, since those
+ don't use executemany()). For a backend that doesn't support
+ cursor.rowcount at all, a warning is emitted the same
+ as with saves.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The ORM now short-term caches the "compiled" form of
+ insert() and update() constructs when flushing lists of
+ objects of all the same class, thereby avoiding redundant
+ compilation per individual INSERT/UPDATE within an
+ individual flush() call.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ internal getattr(), setattr(), getcommitted() methods
+ on ColumnProperty, CompositeProperty, RelationshipProperty
+ have been underscored (i.e. are private), signature has
+ changed.
+
+ .. change::
+ :tags: engines
+ :tickets: 1757
+
+ The C extension now also works with DBAPIs which use custom
+ sequences as row (and not only tuples).
+
+ .. change::
+ :tags: sql
+ :tickets: 1755
+
+ Restored some bind-labeling logic from 0.5 which ensures
+ that tables with column names that overlap another column
+ of the form "<tablename>_<columnname>" won't produce
+ errors if column._label is used as a bind name during
+ an UPDATE. Test coverage which wasn't present in 0.5
+ has been added.
+
+ .. change::
+ :tags: sql
+ :tickets: 1729
+
+ somejoin.select(fold_equivalents=True) is no longer
+ deprecated, and will eventually be rolled into a more
+ comprehensive version of the feature for.
+
+ .. change::
+ :tags: sql
+ :tickets: 1759
+
+ the Numeric type raises an *enormous* warning when expected
+ to convert floats to Decimal from a DBAPI that returns floats.
+ This includes SQLite, Sybase, MS-SQL.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed an error in expression typing which caused an endless
+ loop for expressions with two NULL types.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed bug in execution_options() feature whereby the existing
+ Transaction and other state information from the parent
+ connection would not be propagated to the sub-connection.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added new 'compiled_cache' execution option. A dictionary
+ where Compiled objects will be cached when the Connection
+ compiles a clause expression into a dialect- and parameter-
+ specific Compiled object. It is the user's responsibility to
+ manage the size of this dictionary, which will have keys
+ corresponding to the dialect, clause element, the column
+ names within the VALUES or SET clause of an INSERT or UPDATE,
+ as well as the "batch" mode for an INSERT or UPDATE statement.
+
+ .. change::
+ :tags: sql
+ :tickets: 1769
+
+ Added get_pk_constraint() to reflection.Inspector, similar
+ to get_primary_keys() except returns a dict that includes the
+ name of the constraint, for supported backends (PG so far).
+
+ .. change::
+ :tags: sql
+ :tickets: 1771
+
+ Table.create() and Table.drop() no longer apply metadata-
+ level create/drop events.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ the compiler extension now allows @compiles decorators
+ on base classes that extend to child classes, @compiles
+ decorators on child classes that aren't broken by a
+ @compiles decorator on the base class.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ Declarative will raise an informative error message
+ if a non-mapped class attribute is referenced in the
+ string-based relationship() arguments.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ Further reworked the "mixin" logic in declarative to
+ additionally allow __mapper_args__ as a @classproperty
+ on a mixin, such as to dynamically assign polymorphic_identity.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1071
+
+ Postgresql now reflects sequence names associated with
+ SERIAL columns correctly, after the name of of the sequence
+ has been changed. Thanks to Kumar McMillan for the patch.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ Repaired missing import in psycopg2._PGNumeric type when
+ unknown numeric is received.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ psycopg2/pg8000 dialects now aware of REAL[], FLOAT[],
+ DOUBLE_PRECISION[], NUMERIC[] return types without
+ raising an exception.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1769
+
+ Postgresql reflects the name of primary key constraints,
+ if one exists.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Now using cx_oracle output converters so that the
+ DBAPI returns natively the kinds of values we prefer:
+
+ .. change::
+ :tags: oracle
+ :tickets: 1759
+
+ NUMBER values with positive precision + scale convert
+ to cx_oracle.STRING and then to Decimal. This
+ allows perfect precision for the Numeric type when
+ using cx_oracle.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ STRING/FIXED_CHAR now convert to unicode natively.
+ SQLAlchemy's String types then don't need to
+ apply any kind of conversions.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ The functionality of result.rowcount can be disabled on a
+ per-engine basis by setting 'enable_rowcount=False'
+ on create_engine(). Normally, cursor.rowcount is called
+ after any UPDATE or DELETE statement unconditionally,
+ because the cursor is then closed and Firebird requires
+ an open cursor in order to get a rowcount. This
+ call is slightly expensive however so it can be disabled.
+ To re-enable on a per-execution basis, the
+ 'enable_rowcount=True' execution option may be used.
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ Updated attribute_shard.py example to use a more robust
+ method of searching a Query for binary expressions which
+ compare columns against literal values.
+
+.. changelog::
+ :version: 0.6beta3
+ :released: Sun Mar 28 2010
+
+ .. change::
+ :tags: orm
+ :tickets: 1675
+
+ Major feature: Added new "subquery" loading capability to
+ relationship(). This is an eager loading option which
+ generates a second SELECT for each collection represented
+ in a query, across all parents at once. The query
+ re-issues the original end-user query wrapped in a subquery,
+ applies joins out to the target collection, and loads
+ all those collections fully in one result, similar to
+ "joined" eager loading but using all inner joins and not
+ re-fetching full parent rows repeatedly (as most DBAPIs seem
+ to do, even if columns are skipped). Subquery loading is
+ available at mapper config level using "lazy='subquery'" and
+ at the query options level using "subqueryload(props..)",
+ "subqueryload_all(props...)".
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ To accomodate the fact that there are now two kinds of eager
+ loading available, the new names for eagerload() and
+ eagerload_all() are joinedload() and joinedload_all(). The
+ old names will remain as synonyms for the foreseeable future.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The "lazy" flag on the relationship() function now accepts
+ a string argument for all kinds of loading: "select", "joined",
+ "subquery", "noload" and "dynamic", where the default is now
+ "select". The old values of True/
+ False/None still retain their usual meanings and will remain
+ as synonyms for the foreseeable future.
+
+ .. change::
+ :tags: orm
+ :tickets: 921
+
+ Added with_hint() method to Query() construct. This calls
+ directly down to select().with_hint() and also accepts
+ entities as well as tables and aliases. See with_hint() in the
+ SQL section below.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug in Query whereby calling q.join(prop).from_self(...).
+ join(prop) would fail to render the second join outside the
+ subquery, when joining on the same criterion as was on the
+ inside.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug in Query whereby the usage of aliased() constructs
+ would fail if the underlying table (but not the actual alias)
+ were referenced inside the subquery generated by
+ q.from_self() or q.select_from().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug which affected all eagerload() and similar options
+ such that "remote" eager loads, i.e. eagerloads off of a lazy
+ load such as query(A).options(eagerload(A.b, B.c))
+ wouldn't eagerload anything, but using eagerload("b.c") would
+ work fine.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query gains an add_columns(*columns) method which is a multi-
+ version of add_column(col). add_column(col) is future
+ deprecated.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.join() will detect if the end result will be
+ "FROM A JOIN A", and will raise an error if so.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.join(Cls.propname, from_joinpoint=True) will check more
+ carefully that "Cls" is compatible with the current joinpoint,
+ and act the same way as Query.join("propname", from_joinpoint=True)
+ in that regard.
+
+ .. change::
+ :tags: sql
+ :tickets: 921
+
+ Added with_hint() method to select() construct. Specify
+ a table/alias, hint text, and optional dialect name, and
+ "hints" will be rendered in the appropriate place in the
+ statement. Works for Oracle, Sybase, MySQL.
+
+ .. change::
+ :tags: sql
+ :tickets: 1747
+
+ Fixed bug introduced in 0.6beta2 where column labels would
+ render inside of column expressions already assigned a label.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 877
+
+ The psycopg2 dialect will log NOTICE messages via the
+ "sqlalchemy.dialects.postgresql" logger name.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 997
+
+ the TIME and TIMESTAMP types are now availble from the
+ postgresql dialect directly, which add the PG-specific
+ argument 'precision' to both. 'precision' and
+ 'timezone' are correctly reflected for both TIME and
+ TIMEZONE types.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1752
+
+ No longer guessing that TINYINT(1) should be BOOLEAN
+ when reflecting - TINYINT(1) is returned. Use Boolean/
+ BOOLEAN in table definition to get boolean conversion
+ behavior.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1744
+
+ The Oracle dialect will issue VARCHAR type definitions
+ using character counts, i.e. VARCHAR2(50 CHAR), so that
+ the column is sized in terms of characters and not bytes.
+ Column reflection of character types will also use
+ ALL_TAB_COLUMNS.CHAR_LENGTH instead of
+ ALL_TAB_COLUMNS.DATA_LENGTH. Both of these behaviors take
+ effect when the server version is 9 or higher - for
+ version 8, the old behaviors are used.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1746
+
+ Using a mixin won't break if the mixin implements an
+ unpredictable __getattribute__(), i.e. Zope interfaces.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1749
+
+ Using @classdecorator and similar on mixins to define
+ __tablename__, __table_args__, etc. now works if
+ the method references attributes on the ultimate
+ subclass.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1751
+
+ relationships and columns with foreign keys aren't
+ allowed on declarative mixins, sorry.
+
+ .. change::
+ :tags: ext
+ :tickets:
+
+ The sqlalchemy.orm.shard module now becomes an extension,
+ sqlalchemy.ext.horizontal_shard. The old import
+ works with a deprecation warning.
+
+.. changelog::
+ :version: 0.6beta2
+ :released: Sat Mar 20 2010
+
+ .. change::
+ :tags: py3k
+ :tickets:
+
+ Improved the installation/test setup regarding Python 3,
+ now that Distribute runs on Py3k. distribute_setup.py
+ is now included. See README.py3k for Python 3 installation/
+ testing instructions.
+
+ .. change::
+ :tags: orm
+ :tickets: 1740
+
+ The official name for the relation() function is now
+ relationship(), to eliminate confusion over the relational
+ algebra term. relation() however will remain available
+ in equal capacity for the foreseeable future.
+
+ .. change::
+ :tags: orm
+ :tickets: 1692
+
+ Added "version_id_generator" argument to Mapper, this is a
+ callable that, given the current value of the "version_id_col",
+ returns the next version number. Can be used for alternate
+ versioning schemes such as uuid, timestamps.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added "lockmode" kw argument to Session.refresh(), will
+ pass through the string value to Query the same as
+ in with_lockmode(), will also do version check for a
+ version_id_col-enabled mapping.
+
+ .. change::
+ :tags: orm
+ :tickets: 1188
+
+ Fixed bug whereby calling query(A).join(A.bs).add_entity(B)
+ in a joined inheritance scenario would double-add B as a
+ target and produce an invalid query.
+
+ .. change::
+ :tags: orm
+ :tickets: 1674
+
+ Fixed bug in session.rollback() which involved not removing
+ formerly "pending" objects from the session before
+ re-integrating "deleted" objects, typically occured with
+ natural primary keys. If there was a primary key conflict
+ between them, the attach of the deleted would fail
+ internally. The formerly "pending" objects are now expunged
+ first.
+
+ .. change::
+ :tags: orm
+ :tickets: 1719
+
+ Removed a lot of logging that nobody really cares about,
+ logging that remains will respond to live changes in the
+ log level. No significant overhead is added.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug in session.merge() which prevented dict-like
+ collections from merging.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ session.merge() works with relations that specifically
+ don't include "merge" in their cascade options - the target
+ is ignored completely.
+
+ .. change::
+ :tags: orm
+ :tickets: 1681
+
+ session.merge() will not expire existing scalar attributes
+ on an existing target if the target has a value for that
+ attribute, even if the incoming merged doesn't have
+ a value for the attribute. This prevents unnecessary loads
+ on existing items. Will still mark the attr as expired
+ if the destination doesn't have the attr, though, which
+ fulfills some contracts of deferred cols.
+
+ .. change::
+ :tags: orm
+ :tickets: 1680
+
+ The "allow_null_pks" flag is now called "allow_partial_pks",
+ defaults to True, acts like it did in 0.5 again. Except,
+ it also is implemented within merge() such that a SELECT
+ won't be issued for an incoming instance with partially
+ NULL primary key if the flag is False.
+
+ .. change::
+ :tags: orm
+ :tickets: 1737
+
+ Fixed bug in 0.6-reworked "many-to-one" optimizations
+ such that a many-to-one that is against a non-primary key
+ column on the remote table (i.e. foreign key against a
+ UNIQUE column) will pull the "old" value in from the
+ database during a change, since if it's in the session
+ we will need it for proper history/backref accounting,
+ and we can't pull from the local identity map on a
+ non-primary key column.
+
+ .. change::
+ :tags: orm
+ :tickets: 1731
+
+ fixed internal error which would occur if calling has()
+ or similar complex expression on a single-table inheritance
+ relation().
+
+ .. change::
+ :tags: orm
+ :tickets: 1688
+
+ query.one() no longer applies LIMIT to the query, this to
+ ensure that it fully counts all object identities present
+ in the result, even in the case where joins may conceal
+ multiple identities for two or more rows. As a bonus,
+ one() can now also be called with a query that issued
+ from_statement() to start with since it no longer modifies
+ the query.
+
+ .. change::
+ :tags: orm
+ :tickets: 1727
+
+ query.get() now returns None if queried for an identifier
+ that is present in the identity map with a different class
+ than the one requested, i.e. when using polymorphic loading.
+
+ .. change::
+ :tags: orm
+ :tickets: 1706
+
+ A major fix in query.join(), when the "on" clause is an
+ attribute of an aliased() construct, but there is already
+ an existing join made out to a compatible target, query properly
+ joins to the right aliased() construct instead of sticking
+ onto the right side of the existing join.
+
+ .. change::
+ :tags: orm
+ :tickets: 1362
+
+ Slight improvement to the fix for to not issue
+ needless updates of the primary key column during a so-called
+ "row switch" operation, i.e. add + delete of two objects
+ with the same PK.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Now uses sqlalchemy.orm.exc.DetachedInstanceError when an
+ attribute load or refresh action fails due to object
+ being detached from any Session. UnboundExecutionError
+ is specific to engines bound to sessions and statements.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query called in the context of an expression will render
+ disambiguating labels in all cases. Note that this does
+ not apply to the existing .statement and .subquery()
+ accessor/method, which still honors the .with_labels()
+ setting that defaults to False.
+
+ .. change::
+ :tags: orm
+ :tickets: 1676
+
+ Query.union() retains disambiguating labels within the
+ returned statement, thus avoiding various SQL composition
+ errors which can result from column name conflicts.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed bug in attribute history that inadvertently invoked
+ __eq__ on mapped instances.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Some internal streamlining of object loading grants a
+ small speedup for large results, estimates are around
+ 10-15%. Gave the "state" internals a good solid
+ cleanup with less complexity, datamembers,
+ method calls, blank dictionary creates.
+
+ .. change::
+ :tags: orm
+ :tickets: 1689
+
+ Documentation clarification for query.delete()
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed cascade bug in many-to-one relation() when attribute
+ was set to None, introduced in r6711 (cascade deleted
+ items into session during add()).
+
+ .. change::
+ :tags: orm
+ :tickets: 1736
+
+ Calling query.order_by() or query.distinct() before calling
+ query.select_from(), query.with_polymorphic(), or
+ query.from_statement() raises an exception now instead of
+ silently dropping those criterion.
+
+ .. change::
+ :tags: orm
+ :tickets: 1735
+
+ query.scalar() now raises an exception if more than one
+ row is returned. All other behavior remains the same.
+
+ .. change::
+ :tags: orm
+ :tickets: 1692
+
+ Fixed bug which caused "row switch" logic, that is an
+ INSERT and DELETE replaced by an UPDATE, to fail when
+ version_id_col was in use.
+
+ .. change::
+ :tags: sql
+ :tickets: 1714
+
+ join() will now simulate a NATURAL JOIN by default. Meaning,
+ if the left side is a join, it will attempt to join the right
+ side to the rightmost side of the left first, and not raise
+ any exceptions about ambiguous join conditions if successful
+ even if there are further join targets across the rest of
+ the left.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The most common result processors conversion function were
+ moved to the new "processors" module. Dialect authors are
+ encouraged to use those functions whenever they correspond
+ to their needs instead of implementing custom ones.
+
+ .. change::
+ :tags: sql
+ :tickets: 1694, 1698
+
+ SchemaType and subclasses Boolean, Enum are now serializable,
+ including their ddl listener and other event callables.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Some platforms will now interpret certain literal values
+ as non-bind parameters, rendered literally into the SQL
+ statement. This to support strict SQL-92 rules that are
+ enforced by some platforms including MS-SQL and Sybase.
+ In this model, bind parameters aren't allowed in the
+ columns clause of a SELECT, nor are certain ambiguous
+ expressions like "?=?". When this mode is enabled, the base
+ compiler will render the binds as inline literals, but only across
+ strings and numeric values. Other types such as dates
+ will raise an error, unless the dialect subclass defines
+ a literal rendering function for those. The bind parameter
+ must have an embedded literal value already or an error
+ is raised (i.e. won't work with straight bindparam('x')).
+ Dialects can also expand upon the areas where binds are not
+ accepted, such as within argument lists of functions
+ (which don't work on MS-SQL when native SQL binding is used).
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added "unicode_errors" parameter to String, Unicode, etc.
+ Behaves like the 'errors' keyword argument to
+ the standard library's string.decode() functions. This flag
+ requires that `convert_unicode` is set to `"force"` - otherwise,
+ SQLAlchemy is not guaranteed to handle the task of unicode
+ conversion. Note that this flag adds significant performance
+ overhead to row-fetching operations for backends that already
+ return unicode objects natively (which most DBAPIs do). This
+ flag should only be used as an absolute last resort for reading
+ strings from a column with varied or corrupted encodings,
+ which only applies to databases that accept invalid encodings
+ in the first place (i.e. MySQL. *not* PG, Sqlite, etc.)
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added math negation operator support, -x.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ FunctionElement subclasses are now directly executable the
+ same way any func.foo() construct is, with automatic
+ SELECT being applied when passed to execute().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The "type" and "bind" keyword arguments of a func.foo()
+ construct are now local to "func." constructs and are
+ not part of the FunctionElement base class, allowing
+ a "type" to be handled in a custom constructor or
+ class-level variable.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Restored the keys() method to ResultProxy.
+
+ .. change::
+ :tags: sql
+ :tickets: 1647, 1683
+
+ The type/expression system now does a more complete job
+ of determining the return type from an expression
+ as well as the adaptation of the Python operator into
+ a SQL operator, based on the full left/right/operator
+ of the given expression. In particular
+ the date/time/interval system created for Postgresql
+ EXTRACT in has now been generalized into
+ the type system. The previous behavior which often
+ occured of an expression "column + literal" forcing
+ the type of "literal" to be the same as that of "column"
+ will now usually not occur - the type of
+ "literal" is first derived from the Python type of the
+ literal, assuming standard native Python types + date
+ types, before falling back to that of the known type
+ on the other side of the expression. If the
+ "fallback" type is compatible (i.e. CHAR from String),
+ the literal side will use that. TypeDecorator
+ types override this by default to coerce the "literal"
+ side unconditionally, which can be changed by implementing
+ the coerce_compared_value() method. Also part of.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Made sqlalchemy.sql.expressions.Executable part of public
+ API, used for any expression construct that can be sent to
+ execute(). FunctionElement now inherits Executable so that
+ it gains execution_options(), which are also propagated
+ to the select() that's generated within execute().
+ Executable in turn subclasses _Generative which marks
+ any ClauseElement that supports the @_generative
+ decorator - these may also become "public" for the benefit
+ of the compiler extension at some point.
+
+ .. change::
+ :tags: sql
+ :tickets: 1579
+
+ A change to the solution for - an end-user
+ defined bind parameter name that directly conflicts with
+ a column-named bind generated directly from the SET or
+ VALUES clause of an update/insert generates a compile error.
+ This reduces call counts and eliminates some cases where
+ undesirable name conflicts could still occur.
+
+ .. change::
+ :tags: sql
+ :tickets: 1705
+
+ Column() requires a type if it has no foreign keys (this is
+ not new). An error is now raised if a Column() has no type
+ and no foreign keys.
+
+ .. change::
+ :tags: sql
+ :tickets: 1717
+
+ the "scale" argument of the Numeric() type is honored when
+ coercing a returned floating point value into a string
+ on its way to Decimal - this allows accuracy to function
+ on SQLite, MySQL.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the copy() method of Column now copies over uninitialized
+ "on table attach" events. Helps with the new declarative
+ "mixin" capability.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Added an optional C extension to speed up the sql layer by
+ reimplementing RowProxy and the most common result processors.
+ The actual speedups will depend heavily on your DBAPI and
+ the mix of datatypes used in your tables, and can vary from
+ a 30% improvement to more than 200%. It also provides a modest
+ (~15-20%) indirect improvement to ORM speed for large queries.
+ Note that it is *not* built/installed by default.
+ See README for installation instructions.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ the execution sequence pulls all rowcount/last inserted ID
+ info from the cursor before commit() is called on the
+ DBAPI connection in an "autocommit" scenario. This helps
+ mxodbc with rowcount and is probably a good idea overall.
+
+ .. change::
+ :tags: engines
+ :tickets: 1719
+
+ Opened up logging a bit such that isEnabledFor() is called
+ more often, so that changes to the log level for engine/pool
+ will be reflected on next connect. This adds a small
+ amount of method call overhead. It's negligible and will make
+ life a lot easier for all those situations when logging
+ just happens to be configured after create_engine() is called.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ The assert_unicode flag is deprecated. SQLAlchemy will raise
+ a warning in all cases where it is asked to encode a non-unicode
+ Python string, as well as when a Unicode or UnicodeType type
+ is explicitly passed a bytestring. The String type will do nothing
+ for DBAPIs that already accept Python unicode objects.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Bind parameters are sent as a tuple instead of a list. Some
+ backend drivers will not accept bind parameters as a list.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ threadlocal engine wasn't properly closing the connection
+ upon close() - fixed that.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Transaction object doesn't rollback or commit if it isn't
+ "active", allows more accurate nesting of begin/rollback/commit.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Python unicode objects as binds result in the Unicode type,
+ not string, thus eliminating a certain class of unicode errors
+ on drivers that don't support unicode binds.
+
+ .. change::
+ :tags: engines
+ :tickets: 1555
+
+ Added "logging_name" argument to create_engine(), Pool() constructor
+ as well as "pool_logging_name" argument to create_engine() which
+ filters down to that of Pool. Issues the given string name
+ within the "name" field of logging messages instead of the default
+ hex identifier string.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ The visit_pool() method of Dialect is removed, and replaced with
+ on_connect(). This method returns a callable which receives
+ the raw DBAPI connection after each one is created. The callable
+ is assembled into a first_connect/connect pool listener by the
+ connection strategy if non-None. Provides a simpler interface
+ for dialects.
+
+ .. change::
+ :tags: engines
+ :tickets: 1728
+
+ StaticPool now initializes, disposes and recreates without
+ opening a new connection - the connection is only opened when
+ first requested. dispose() also works on AssertionPool now.
+
+ .. change::
+ :tags: ticket: 1673, metadata
+ :tickets:
+
+ Added the ability to strip schema information when using
+ "tometadata" by passing "schema=None" as an argument. If schema
+ is not specified then the table's schema is retained.
+
+ .. change::
+ :tags: declarative
+ :tickets:
+
+ DeclarativeMeta exclusively uses cls.__dict__ (not dict_)
+ as the source of class information; _as_declarative exclusively
+ uses the dict_ passed to it as the source of class information
+ (which when using DeclarativeMeta is cls.__dict__). This should
+ in theory make it easier for custom metaclasses to modify
+ the state passed into _as_declarative.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1707
+
+ declarative now accepts mixin classes directly, as a means
+ to provide common functional and column-based elements on
+ all subclasses, as well as a means to propagate a fixed
+ set of __table_args__ or __mapper_args__ to subclasses.
+ For custom combinations of __table_args__/__mapper_args__ from
+ an inherited mixin to local, descriptors can now be used.
+ New details are all up in the Declarative documentation.
+ Thanks to Chris Withers for putting up with my strife
+ on this.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1393
+
+ the __mapper_args__ dict is copied when propagating to a subclass,
+ and is taken straight off the class __dict__ to avoid any
+ propagation from the parent. mapper inheritance already
+ propagates the things you want from the parent mapper.
+
+ .. change::
+ :tags: declarative
+ :tickets: 1732
+
+ An exception is raised when a single-table subclass specifies
+ a column that is already present on the base class.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1655
+
+ Fixed reflection bug whereby when COLLATE was present,
+ nullable flag and server defaults would not be reflected.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Fixed reflection of TINYINT(1) "boolean" columns defined with
+ integer flags like UNSIGNED.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1668
+
+ Further fixes for the mysql-connector dialect.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1496
+
+ Composite PK table on InnoDB where the "autoincrement" column
+ isn't first will emit an explicit "KEY" phrase within
+ CREATE TABLE thereby avoiding errors.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1634
+
+ Added reflection/create table support for a wide range
+ of MySQL keywords.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1580
+
+ Fixed import error which could occur reflecting tables on
+ a Windows host
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Re-established support for the pymssql dialect.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Various fixes for implicit returning, reflection,
+ etc. - the MS-SQL dialects aren't quite complete
+ in 0.6 yet (but are close)
+
+ .. change::
+ :tags: mssql
+ :tickets: 1710
+
+ Added basic support for mxODBC.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Removed the text_as_varchar option.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ "out" parameters require a type that is supported by
+ cx_oracle. An error will be raised if no cx_oracle
+ type can be found.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Oracle 'DATE' now does not perform any result processing,
+ as the DATE type in Oracle stores full date+time objects,
+ that's what you'll get. Note that the generic types.Date
+ type *will* still call value.date() on incoming values,
+ however. When reflecting a table, the reflected type
+ will be 'DATE'.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1670
+
+ Added preliminary support for Oracle's WITH_UNICODE
+ mode. At the very least this establishes initial
+ support for cx_Oracle with Python 3. When WITH_UNICODE
+ mode is used in Python 2.xx, a large and scary warning
+ is emitted asking that the user seriously consider
+ the usage of this difficult mode of operation.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1712
+
+ The except_() method now renders as MINUS on Oracle,
+ which is more or less equivalent on that platform.
+
+ .. change::
+ :tags: oracle
+ :tickets: 651
+
+ Added support for rendering and reflecting
+ TIMESTAMP WITH TIME ZONE, i.e. TIMESTAMP(timezone=True).
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Oracle INTERVAL type can now be reflected.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 1685
+
+ Added "native_datetime=True" flag to create_engine().
+ This will cause the DATE and TIMESTAMP types to skip
+ all bind parameter and result row processing, under
+ the assumption that PARSE_DECLTYPES has been enabled
+ on the connection. Note that this is not entirely
+ compatible with the "func.current_date()", which
+ will be returned as a string.
+
+ .. change::
+ :tags: sybase
+ :tickets:
+
+ Implemented a preliminary working dialect for Sybase,
+ with sub-implementations for Python-Sybase as well
+ as Pyodbc. Handles table
+ creates/drops and basic round trip functionality.
+ Does not yet include reflection or comprehensive
+ support of unicode/special expressions/etc.
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ Changed the beaker cache example a bit to have a separate
+ RelationCache option for lazyload caching. This object
+ does a lookup among any number of potential attributes
+ more efficiently by grouping several into a common structure.
+ Both FromCache and RelationCache are simpler individually.
+
+ .. change::
+ :tags: documentation
+ :tickets: 1700
+
+ Major cleanup work in the docs to link class, function, and
+ method names into the API docs.
+
+.. changelog::
+ :version: 0.6beta1
+ :released: Wed Feb 03 2010
+
+ .. change::
+ :tags: release, major
+ :tickets:
+
+ For the full set of feature descriptions, see
+ http://www.sqlalchemy.org/trac/wiki/06Migration .
+ This document is a work in progress.
+
+ .. change::
+ :tags: release, major
+ :tickets:
+
+ All bug fixes and feature enhancements from the most
+ recent 0.5 version and below are also included within 0.6.
+
+ .. change::
+ :tags: release, major
+ :tickets:
+
+ Platforms targeted now include Python 2.4/2.5/2.6, Python
+ 3.1, Jython2.5.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Changes to query.update() and query.delete():
+ - the 'expire' option on query.update() has been renamed to
+ 'fetch', thus matching that of query.delete().
+ 'expire' is deprecated and issues a warning.
+
+ - query.update() and query.delete() both default to
+ 'evaluate' for the synchronize strategy.
+
+ - the 'synchronize' strategy for update() and delete()
+ raises an error on failure. There is no implicit fallback
+ onto "fetch". Failure of evaluation is based on the
+ structure of criteria, so success/failure is deterministic
+ based on code structure.
+
+ .. change::
+ :tags: orm
+ :tickets: 1186, 1492, 1544
+
+ Enhancements on many-to-one relations:
+ - many-to-one relations now fire off a lazyload in fewer
+ cases, including in most cases will not fetch the "old"
+ value when a new one is replaced.
+
+ - many-to-one relation to a joined-table subclass now uses
+ get() for a simple load (known as the "use_get"
+ condition), i.e. Related->Sub(Base), without the need to
+ redefine the primaryjoin condition in terms of the base
+ table.
+
+ - specifying a foreign key with a declarative column, i.e.
+ ForeignKey(MyRelatedClass.id) doesn't break the "use_get"
+ condition from taking place
+
+ - relation(), eagerload(), and eagerload_all() now feature
+ an option called "innerjoin". Specify `True` or `False` to
+ control whether an eager join is constructed as an INNER
+ or OUTER join. Default is `False` as always. The mapper
+ options will override whichever setting is specified on
+ relation(). Should generally be set for many-to-one, not
+ nullable foreign key relations to allow improved join
+ performance.
+
+ - the behavior of eagerloading such that the main query is
+ wrapped in a subquery when LIMIT/OFFSET are present now
+ makes an exception for the case when all eager loads are
+ many-to-one joins. In those cases, the eager joins are
+ against the parent table directly along with the
+ limit/offset without the extra overhead of a subquery,
+ since a many-to-one join does not add rows to the result.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Enhancements / Changes on Session.merge():
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the "dont_load=True" flag on Session.merge() is deprecated
+ and is now "load=False".
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Session.merge() is performance optimized, using half the
+ call counts for "load=False" mode compared to 0.5 and
+ significantly fewer SQL queries in the case of collections
+ for "load=True" mode.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ merge() will not issue a needless merge of attributes if the
+ given instance is the same instance which is already present.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ merge() now also merges the "options" associated with a given
+ state, i.e. those passed through query.options() which follow
+ along with an instance, such as options to eagerly- or
+ lazyily- load various attributes. This is essential for
+ the construction of highly integrated caching schemes. This
+ is a subtle behavioral change vs. 0.5.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ A bug was fixed regarding the serialization of the "loader
+ path" present on an instance's state, which is also necessary
+ when combining the usage of merge() with serialized state
+ and associated options that should be preserved.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The all new merge() is showcased in a new comprehensive
+ example of how to integrate Beaker with SQLAlchemy. See
+ the notes in the "examples" note below.
+
+ .. change::
+ :tags: orm
+ :tickets: 1362
+
+ Primary key values can now be changed on a joined-table inheritance
+ object, and ON UPDATE CASCADE will be taken into account when
+ the flush happens. Set the new "passive_updates" flag to False
+ on mapper() when using SQLite or MySQL/MyISAM.
+
+ .. change::
+ :tags: orm
+ :tickets: 1671
+
+ flush() now detects when a primary key column was updated by
+ an ON UPDATE CASCADE operation from another primary key, and
+ can then locate the row for a subsequent UPDATE on the new PK
+ value. This occurs when a relation() is there to establish
+ the relationship as well as passive_updates=True.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the "save-update" cascade will now cascade the pending *removed*
+ values from a scalar or collection attribute into the new session
+ during an add() operation. This so that the flush() operation
+ will also delete or modify rows of those disconnected items.
+
+ .. change::
+ :tags: orm
+ :tickets: 1531
+
+ Using a "dynamic" loader with a "secondary" table now produces
+ a query where the "secondary" table is *not* aliased. This
+ allows the secondary Table object to be used in the "order_by"
+ attribute of the relation(), and also allows it to be used
+ in filter criterion against the dynamic relation.
+
+ .. change::
+ :tags: orm
+ :tickets: 1643
+
+ relation() with uselist=False will emit a warning when
+ an eager or lazy load locates more than one valid value for
+ the row. This may be due to primaryjoin/secondaryjoin
+ conditions which aren't appropriate for an eager LEFT OUTER
+ JOIN or for other conditions.
+
+ .. change::
+ :tags: orm
+ :tickets: 1633
+
+ an explicit check occurs when a synonym() is used with
+ map_column=True, when a ColumnProperty (deferred or otherwise)
+ exists separately in the properties dictionary sent to mapper
+ with the same keyname. Instead of silently replacing
+ the existing property (and possible options on that property),
+ an error is raised.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ a "dynamic" loader sets up its query criterion at construction
+ time so that the actual query is returned from non-cloning
+ accessors like "statement".
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the "named tuple" objects returned when iterating a
+ Query() are now pickleable.
+
+ .. change::
+ :tags: orm
+ :tickets: 1542
+
+ mapping to a select() construct now requires that you
+ make an alias() out of it distinctly. This to eliminate
+ confusion over such issues as
+
+ .. change::
+ :tags: orm
+ :tickets: 1537
+
+ query.join() has been reworked to provide more consistent
+ behavior and more flexibility (includes)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.select_from() accepts multiple clauses to produce
+ multiple comma separated entries within the FROM clause.
+ Useful when selecting from multiple-homed join() clauses.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ query.select_from() also accepts mapped classes, aliased()
+ constructs, and mappers as arguments. In particular this
+ helps when querying from multiple joined-table classes to ensure
+ the full join gets rendered.
+
+ .. change::
+ :tags: orm
+ :tickets: 1135
+
+ query.get() can be used with a mapping to an outer join
+ where one or more of the primary key values are None.
+
+ .. change::
+ :tags: orm
+ :tickets: 1568
+
+ query.from_self(), query.union(), others which do a
+ "SELECT * from (SELECT...)" type of nesting will do
+ a better job translating column expressions within the subquery
+ to the columns clause of the outer query. This is
+ potentially backwards incompatible with 0.5, in that this
+ may break queries with literal expressions that do not have labels
+ applied (i.e. literal('foo'), etc.)
+
+ .. change::
+ :tags: orm
+ :tickets: 1622
+
+ relation primaryjoin and secondaryjoin now check that they
+ are column-expressions, not just clause elements. this prohibits
+ things like FROM expressions being placed there directly.
+
+ .. change::
+ :tags: orm
+ :tickets: 1415
+
+ `expression.null()` is fully understood the same way
+ None is when comparing an object/collection-referencing
+ attribute within query.filter(), filter_by(), etc.
+
+ .. change::
+ :tags: orm
+ :tickets: 1052
+
+ added "make_transient()" helper function which transforms a
+ persistent/ detached instance into a transient one (i.e.
+ deletes the instance_key and removes from any session.)
+
+ .. change::
+ :tags: orm
+ :tickets: 1339
+
+ the allow_null_pks flag on mapper() is deprecated, and
+ the feature is turned "on" by default. This means that
+ a row which has a non-null value for any of its primary key
+ columns will be considered an identity. The need for this
+ scenario typically only occurs when mapping to an outer join.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the mechanics of "backref" have been fully merged into the
+ finer grained "back_populates" system, and take place entirely
+ within the _generate_backref() method of RelationProperty. This
+ makes the initialization procedure of RelationProperty
+ simpler and allows easier propagation of settings (such as from
+ subclasses of RelationProperty) into the reverse reference.
+ The internal BackRef() is gone and backref() returns a plain
+ tuple that is understood by RelationProperty.
+
+ .. change::
+ :tags: orm
+ :tickets: 1569
+
+ The version_id_col feature on mapper() will raise a warning when
+ used with dialects that don't support "rowcount" adequately.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added "execution_options()" to Query, to so options can be
+ passed to the resulting statement. Currently only
+ Select-statements have these options, and the only option
+ used is "stream_results", and the only dialect which knows
+ "stream_results" is psycopg2.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.yield_per() will set the "stream_results" statement
+ option automatically.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Deprecated or removed:
+ * 'allow_null_pks' flag on mapper() is deprecated. It does
+ nothing now and the setting is "on" in all cases.
+ * 'transactional' flag on sessionmaker() and others is
+ removed. Use 'autocommit=True' to indicate 'transactional=False'.
+ * 'polymorphic_fetch' argument on mapper() is removed.
+ Loading can be controlled using the 'with_polymorphic'
+ option.
+ * 'select_table' argument on mapper() is removed. Use
+ 'with_polymorphic=("*", <some selectable>)' for this
+ functionality.
+ * 'proxy' argument on synonym() is removed. This flag
+ did nothing throughout 0.5, as the "proxy generation"
+ behavior is now automatic.
+ * Passing a single list of elements to eagerload(),
+ eagerload_all(), contains_eager(), lazyload(),
+ defer(), and undefer() instead of multiple positional
+ *args is deprecated.
+ * Passing a single list of elements to query.order_by(),
+ query.group_by(), query.join(), or query.outerjoin()
+ instead of multiple positional *args is deprecated.
+ * query.iterate_instances() is removed. Use query.instances().
+ * Query.query_from_parent() is removed. Use the
+ sqlalchemy.orm.with_parent() function to produce a
+ "parent" clause, or alternatively query.with_parent().
+ * query._from_self() is removed, use query.from_self()
+ instead.
+ * the "comparator" argument to composite() is removed.
+ Use "comparator_factory".
+ * RelationProperty._get_join() is removed.
+ * the 'echo_uow' flag on Session is removed. Use
+ logging on the "sqlalchemy.orm.unitofwork" name.
+ * session.clear() is removed. use session.expunge_all().
+ * session.save(), session.update(), session.save_or_update()
+ are removed. Use session.add() and session.add_all().
+ * the "objects" flag on session.flush() remains deprecated.
+ * the "dont_load=True" flag on session.merge() is deprecated
+ in favor of "load=False".
+ * ScopedSession.mapper remains deprecated. See the
+ usage recipe at
+ http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper
+ * passing an InstanceState (internal SQLAlchemy state object) to
+ attributes.init_collection() or attributes.get_history() is
+ deprecated. These functions are public API and normally
+ expect a regular mapped object instance.
+ * the 'engine' parameter to declarative_base() is removed.
+ Use the 'bind' keyword argument.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the "autocommit" flag on select() and text() as well
+ as select().autocommit() are deprecated - now call
+ .execution_options(autocommit=True) on either of those
+ constructs, also available directly on Connection and orm.Query.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ the autoincrement flag on column now indicates the column
+ which should be linked to cursor.lastrowid, if that method
+ is used. See the API docs for details.
+
+ .. change::
+ :tags: sql
+ :tickets: 1566
+
+ an executemany() now requires that all bound parameter
+ sets require that all keys are present which are
+ present in the first bound parameter set. The structure
+ and behavior of an insert/update statement is very much
+ determined by the first parameter set, including which
+ defaults are going to fire off, and a minimum of
+ guesswork is performed with all the rest so that performance
+ is not impacted. For this reason defaults would otherwise
+ silently "fail" for missing parameters, so this is now guarded
+ against.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ returning() support is native to insert(), update(),
+ delete(). Implementations of varying levels of
+ functionality exist for Postgresql, Firebird, MSSQL and
+ Oracle. returning() can be called explicitly with column
+ expressions which are then returned in the resultset,
+ usually via fetchone() or first().
+
+ insert() constructs will also use RETURNING implicitly to
+ get newly generated primary key values, if the database
+ version in use supports it (a version number check is
+ performed). This occurs if no end-user returning() was
+ specified.
+
+ .. change::
+ :tags: sql
+ :tickets: 1665
+
+ union(), intersect(), except() and other "compound" types
+ of statements have more consistent behavior w.r.t.
+ parenthesizing. Each compound element embedded within
+ another will now be grouped with parenthesis - previously,
+ the first compound element in the list would not be grouped,
+ as SQLite doesn't like a statement to start with
+ parenthesis. However, Postgresql in particular has
+ precedence rules regarding INTERSECT, and it is
+ more consistent for parenthesis to be applied equally
+ to all sub-elements. So now, the workaround for SQLite
+ is also what the workaround for PG was previously -
+ when nesting compound elements, the first one usually needs
+ ".alias().select()" called on it to wrap it inside
+ of a subquery.
+
+ .. change::
+ :tags: sql
+ :tickets: 1579
+
+ insert() and update() constructs can now embed bindparam()
+ objects using names that match the keys of columns. These
+ bind parameters will circumvent the usual route to those
+ keys showing up in the VALUES or SET clause of the generated
+ SQL.
+
+ .. change::
+ :tags: sql
+ :tickets: 1524
+
+ the Binary type now returns data as a Python string
+ (or a "bytes" type in Python 3), instead of the built-
+ in "buffer" type. This allows symmetric round trips
+ of binary data.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added a tuple_() construct, allows sets of expressions
+ to be compared to another set, typically with IN against
+ composite primary keys or similar. Also accepts an
+ IN with multiple columns. The "scalar select can
+ have only one column" error message is removed - will
+ rely upon the database to report problems with
+ col mismatch.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ User-defined "default" and "onupdate" callables which
+ accept a context should now call upon
+ "context.current_parameters" to get at the dictionary
+ of bind parameters currently being processed. This
+ dict is available in the same way regardless of
+ single-execute or executemany-style statement execution.
+
+ .. change::
+ :tags: sql
+ :tickets: 1428
+
+ multi-part schema names, i.e. with dots such as
+ "dbo.master", are now rendered in select() labels
+ with underscores for dots, i.e. "dbo_master_table_column".
+ This is a "friendly" label that behaves better
+ in result sets.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ removed needless "counter" behavior with select()
+ labelnames that match a column name in the table,
+ i.e. generates "tablename_id" for "id", instead of
+ "tablename_id_1" in an attempt to avoid naming
+ conflicts, when the table has a column actually
+ named "tablename_id" - this is because
+ the labeling logic is always applied to all columns
+ so a naming conflict will never occur.
+
+ .. change::
+ :tags: sql
+ :tickets: 1628
+
+ calling expr.in_([]), i.e. with an empty list, emits a warning
+ before issuing the usual "expr != expr" clause. The
+ "expr != expr" can be very expensive, and it's preferred
+ that the user not issue in_() if the list is empty,
+ instead simply not querying, or modifying the criterion
+ as appropriate for more complex situations.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added "execution_options()" to select()/text(), which set the
+ default options for the Connection. See the note in "engines".
+
+ .. change::
+ :tags: sql
+ :tickets: 1131
+
+ Deprecated or removed:
+ * "scalar" flag on select() is removed, use
+ select.as_scalar().
+ * "shortname" attribute on bindparam() is removed.
+ * postgres_returning, firebird_returning flags on
+ insert(), update(), delete() are deprecated, use
+ the new returning() method.
+ * fold_equivalents flag on join is deprecated (will remain
+ until is implemented)
+
+ .. change::
+ :tags: engines
+ :tickets: 443
+
+ transaction isolation level may be specified with
+ create_engine(... isolation_level="..."); available on
+ postgresql and sqlite.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Connection has execution_options(), generative method
+ which accepts keywords that affect how the statement
+ is executed w.r.t. the DBAPI. Currently supports
+ "stream_results", causes psycopg2 to use a server
+ side cursor for that statement, as well as
+ "autocommit", which is the new location for the "autocommit"
+ option from select() and text(). select() and
+ text() also have .execution_options() as well as
+ ORM Query().
+
+ .. change::
+ :tags: engines
+ :tickets: 1630
+
+ fixed the import for entrypoint-driven dialects to
+ not rely upon silly tb_info trick to determine import
+ error status.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ added first() method to ResultProxy, returns first row and
+ closes result set immediately.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ RowProxy objects are now pickleable, i.e. the object returned
+ by result.fetchone(), result.fetchall() etc.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ RowProxy no longer has a close() method, as the row no longer
+ maintains a reference to the parent. Call close() on
+ the parent ResultProxy instead, or use autoclose.
+
+ .. change::
+ :tags: engines
+ :tickets: 1586
+
+ ResultProxy internals have been overhauled to greatly reduce
+ method call counts when fetching columns. Can provide a large
+ speed improvement (up to more than 100%) when fetching large
+ result sets. The improvement is larger when fetching columns
+ that have no type-level processing applied and when using
+ results as tuples (instead of as dictionaries). Many
+ thanks to Elixir's Gaëtan de Menten for this dramatic
+ improvement !
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Databases which rely upon postfetch of "last inserted id"
+ to get at a generated sequence value (i.e. MySQL, MS-SQL)
+ now work correctly when there is a composite primary key
+ where the "autoincrement" column is not the first primary
+ key column in the table.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ the last_inserted_ids() method has been renamed to the
+ descriptor "inserted_primary_key".
+
+ .. change::
+ :tags: engines
+ :tickets: 1554
+
+ setting echo=False on create_engine() now sets the loglevel
+ to WARN instead of NOTSET. This so that logging can be
+ disabled for a particular engine even if logging
+ for "sqlalchemy.engine" is enabled overall. Note that the
+ default setting of "echo" is `None`.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ ConnectionProxy now has wrapper methods for all transaction
+ lifecycle events, including begin(), rollback(), commit()
+ begin_nested(), begin_prepared(), prepare(), release_savepoint(),
+ etc.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ Connection pool logging now uses both INFO and DEBUG
+ log levels for logging. INFO is for major events such
+ as invalidated connections, DEBUG for all the acquire/return
+ logging. `echo_pool` can be False, None, True or "debug"
+ the same way as `echo` works.
+
+ .. change::
+ :tags: engines
+ :tickets: 1621
+
+ All pyodbc-dialects now support extra pyodbc-specific
+ kw arguments 'ansi', 'unicode_results', 'autocommit'.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ the "threadlocal" engine has been rewritten and simplified
+ and now supports SAVEPOINT operations.
+
+ .. change::
+ :tags: engines
+ :tickets:
+
+ deprecated or removed
+ * result.last_inserted_ids() is deprecated. Use
+ result.inserted_primary_key
+ * dialect.get_default_schema_name(connection) is now
+ public via dialect.default_schema_name.
+ * the "connection" argument from engine.transaction() and
+ engine.run_callable() is removed - Connection itself
+ now has those methods. All four methods accept
+ *args and **kwargs which are passed to the given callable,
+ as well as the operating connection.
+
+ .. change::
+ :tags: schema
+ :tickets: 1541
+
+ the `__contains__()` method of `MetaData` now accepts
+ strings or `Table` objects as arguments. If given
+ a `Table`, the argument is converted to `table.key` first,
+ i.e. "[schemaname.]<tablename>"
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ deprecated MetaData.connect() and
+ ThreadLocalMetaData.connect() have been removed - send
+ the "bind" attribute to bind a metadata.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ deprecated metadata.table_iterator() method removed (use
+ sorted_tables)
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ deprecated PassiveDefault - use DefaultClause.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ the "metadata" argument is removed from DefaultGenerator
+ and subclasses, but remains locally present on Sequence,
+ which is a standalone construct in DDL.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Removed public mutability from Index and Constraint
+ objects:
+ - ForeignKeyConstraint.append_element()
+ - Index.append_column()
+ - UniqueConstraint.append_column()
+ - PrimaryKeyConstraint.add()
+ - PrimaryKeyConstraint.remove()
+ These should be constructed declaratively (i.e. in one
+ construction).
+
+ .. change::
+ :tags: schema
+ :tickets: 1545
+
+ The "start" and "increment" attributes on Sequence now
+ generate "START WITH" and "INCREMENT BY" by default,
+ on Oracle and Postgresql. Firebird doesn't support
+ these keywords right now.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ UniqueConstraint, Index, PrimaryKeyConstraint all accept
+ lists of column names or column objects as arguments.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Other removed things:
+ - Table.key (no idea what this was for)
+ - Table.primary_key is not assignable - use
+ table.append_constraint(PrimaryKeyConstraint(...))
+ - Column.bind (get via column.table.bind)
+ - Column.metadata (get via column.table.metadata)
+ - Column.sequence (use column.default)
+ - ForeignKey(constraint=some_parent) (is now private _constraint)
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ The use_alter flag on ForeignKey is now a shortcut option
+ for operations that can be hand-constructed using the
+ DDL() event system. A side effect of this refactor is
+ that ForeignKeyConstraint objects with use_alter=True
+ will *not* be emitted on SQLite, which does not support
+ ALTER for foreign keys.
+
+ .. change::
+ :tags: schema
+ :tickets: 1605
+
+ ForeignKey and ForeignKeyConstraint objects now correctly
+ copy() all their public keyword arguments.
+
+ .. change::
+ :tags: reflection/inspection
+ :tickets:
+
+ Table reflection has been expanded and generalized into
+ a new API called "sqlalchemy.engine.reflection.Inspector".
+ The Inspector object provides fine-grained information about
+ a wide variety of schema information, with room for expansion,
+ including table names, column names, view definitions, sequences,
+ indexes, etc.
+
+ .. change::
+ :tags: reflection/inspection
+ :tickets:
+
+ Views are now reflectable as ordinary Table objects. The same
+ Table constructor is used, with the caveat that "effective"
+ primary and foreign key constraints aren't part of the reflection
+ results; these have to be specified explicitly if desired.
+
+ .. change::
+ :tags: reflection/inspection
+ :tickets:
+
+ The existing autoload=True system now uses Inspector underneath
+ so that each dialect need only return "raw" data about tables
+ and other objects - Inspector is the single place that information
+ is compiled into Table objects so that consistency is at a maximum.
+
+ .. change::
+ :tags: ddl
+ :tickets:
+
+ the DDL system has been greatly expanded. the DDL() class
+ now extends the more generic DDLElement(), which forms the basis
+ of many new constructs:
+
+ - CreateTable()
+ - DropTable()
+ - AddConstraint()
+ - DropConstraint()
+ - CreateIndex()
+ - DropIndex()
+ - CreateSequence()
+ - DropSequence()
+
+ These support "on" and "execute-at()" just like plain DDL()
+ does. User-defined DDLElement subclasses can be created and
+ linked to a compiler using the sqlalchemy.ext.compiler extension.
+
+ .. change::
+ :tags: ddl
+ :tickets:
+
+ The signature of the "on" callable passed to DDL() and
+ DDLElement() is revised as follows:
+
+ "ddl" - the DDLElement object itself.
+ "event" - the string event name.
+ "target" - previously "schema_item", the Table or
+ MetaData object triggering the event.
+ "connection" - the Connection object in use for the operation.
+ **kw - keyword arguments. In the case of MetaData before/after
+ create/drop, the list of Table objects for which
+ CREATE/DROP DDL is to be issued is passed as the kw
+ argument "tables". This is necessary for metadata-level
+ DDL that is dependent on the presence of specific tables.
+
+ - the "schema_item" attribute of DDL has been renamed to
+ "target".
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ Dialect modules are now broken into database dialects
+ plus DBAPI implementations. Connect URLs are now
+ preferred to be specified using dialect+driver://...,
+ i.e. "mysql+mysqldb://scott:tiger@localhost/test". See
+ the 0.6 documentation for examples.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ the setuptools entrypoint for external dialects is now
+ called "sqlalchemy.dialects".
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ the "owner" keyword argument is removed from Table. Use
+ "schema" to represent any namespaces to be prepended to
+ the table name.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ server_version_info becomes a static attribute.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ dialects receive an initialize() event on initial
+ connection to determine connection properties.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ dialects receive a visit_pool event have an opportunity
+ to establish pool listeners.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ cached TypeEngine classes are cached per-dialect class
+ instead of per-dialect.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ new UserDefinedType should be used as a base class for
+ new types, which preserves the 0.5 behavior of
+ get_col_spec().
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ The result_processor() method of all type classes now
+ accepts a second argument "coltype", which is the DBAPI
+ type argument from cursor.description. This argument
+ can help some types decide on the most efficient processing
+ of result values.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ Deprecated Dialect.get_params() removed.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ Dialect.get_rowcount() has been renamed to a descriptor
+ "rowcount", and calls cursor.rowcount directly. Dialects
+ which need to hardwire a rowcount in for certain calls
+ should override the method to provide different behavior.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets: 1566
+
+ DefaultRunner and subclasses have been removed. The job
+ of this object has been simplified and moved into
+ ExecutionContext. Dialects which support sequences should
+ add a `fire_sequence()` method to their execution context
+ implementation.
+
+ .. change::
+ :tags: dialect, refactor
+ :tickets:
+
+ Functions and operators generated by the compiler now use
+ (almost) regular dispatch functions of the form
+ "visit_<opname>" and "visit_<funcname>_fn" to provide
+ customed processing. This replaces the need to copy the
+ "functions" and "operators" dictionaries in compiler
+ subclasses with straightforward visitor methods, and also
+ allows compiler subclasses complete control over
+ rendering, as the full _Function or _BinaryExpression
+ object is passed in.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ New dialects: pg8000, zxjdbc, and pypostgresql
+ on py3k.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ The "postgres" dialect is now named "postgresql" !
+ Connection strings look like:
+
+ postgresql://scott:tiger@localhost/test
+ postgresql+pg8000://scott:tiger@localhost/test
+
+ The "postgres" name remains for backwards compatiblity
+ in the following ways:
+
+ - There is a "postgres.py" dummy dialect which
+ allows old URLs to work, i.e.
+ postgres://scott:tiger@localhost/test
+
+ - The "postgres" name can be imported from the old
+ "databases" module, i.e. "from
+ sqlalchemy.databases import postgres" as well as
+ "dialects", "from sqlalchemy.dialects.postgres
+ import base as pg", will send a deprecation
+ warning.
+
+ - Special expression arguments are now named
+ "postgresql_returning" and "postgresql_where", but
+ the older "postgres_returning" and
+ "postgres_where" names still work with a
+ deprecation warning.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ "postgresql_where" now accepts SQL expressions which
+ can also include literals, which will be quoted as needed.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ The psycopg2 dialect now uses psycopg2's "unicode extension"
+ on all new connections, which allows all String/Text/etc.
+ types to skip the need to post-process bytestrings into
+ unicode (an expensive step due to its volume). Other
+ dialects which return unicode natively (pg8000, zxjdbc)
+ also skip unicode post-processing.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1511
+
+ Added new ENUM type, which exists as a schema-level
+ construct and extends the generic Enum type. Automatically
+ associates itself with tables and their parent metadata
+ to issue the appropriate CREATE TYPE/DROP TYPE
+ commands as needed, supports unicode labels, supports
+ reflection.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ INTERVAL supports an optional "precision" argument
+ corresponding to the argument that PG accepts.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ using new dialect.initialize() feature to set up
+ version-dependent behavior.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1279
+
+ somewhat better support for % signs in table/column names;
+ psycopg2 can't handle a bind parameter name of
+ %(foobar)s however and SQLA doesn't want to add overhead
+ just to treat that one non-existent use case.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1516
+
+ Inserting NULL into a primary key + foreign key column
+ will allow the "not null constraint" error to raise,
+ not an attempt to execute a nonexistent "col_id_seq"
+ sequence.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ autoincrement SELECT statements, i.e. those which
+ select from a procedure that modifies rows, now work
+ with server-side cursor mode (the named cursor isn't
+ used for such statements.)
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1636
+
+ postgresql dialect can properly detect pg "devel" version
+ strings, i.e. "8.5devel"
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1619
+
+ The psycopg2 now respects the statement option
+ "stream_results". This option overrides the connection setting
+ "server_side_cursors". If true, server side cursors will be
+ used for the statement. If false, they will not be used, even
+ if "server_side_cursors" is true on the
+ connection.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ New dialects: oursql, a new native dialect,
+ MySQL Connector/Python, a native Python port of MySQLdb,
+ and of course zxjdbc on Jython.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ VARCHAR/NVARCHAR will not render without a length, raises
+ an error before passing to MySQL. Doesn't impact
+ CAST since VARCHAR is not allowed in MySQL CAST anyway,
+ the dialect renders CHAR/NCHAR in those cases.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ all the _detect_XXX() functions now run once underneath
+ dialect.initialize()
+
+ .. change::
+ :tags: mysql
+ :tickets: 1279
+
+ somewhat better support for % signs in table/column names;
+ MySQLdb can't handle % signs in SQL when executemany() is used,
+ and SQLA doesn't want to add overhead just to treat that one
+ non-existent use case.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ the BINARY and MSBinary types now generate "BINARY" in all
+ cases. Omitting the "length" parameter will generate
+ "BINARY" with no length. Use BLOB to generate an unlengthed
+ binary column.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ the "quoting='quoted'" argument to MSEnum/ENUM is deprecated.
+ It's best to rely upon the automatic quoting.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ ENUM now subclasses the new generic Enum type, and also handles
+ unicode values implicitly, if the given labelnames are unicode
+ objects.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1539
+
+ a column of type TIMESTAMP now defaults to NULL if
+ "nullable=False" is not passed to Column(), and no default
+ is present. This is now consistent with all other types,
+ and in the case of TIMESTAMP explictly renders "NULL"
+ due to MySQL's "switching" of default nullability
+ for TIMESTAMP columns.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ unit tests pass 100% with cx_oracle !
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ support for cx_Oracle's "native unicode" mode which does
+ not require NLS_LANG to be set. Use the latest 5.0.2 or
+ later of cx_oracle.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ an NCLOB type is added to the base types.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ use_ansi=False won't leak into the FROM/WHERE clause of
+ a statement that's selecting from a subquery that also
+ uses JOIN/OUTERJOIN.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1467
+
+ added native INTERVAL type to the dialect. This supports
+ only the DAY TO SECOND interval type so far due to lack
+ of support in cx_oracle for YEAR TO MONTH.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ usage of the CHAR type results in cx_oracle's
+ FIXED_CHAR dbapi type being bound to statements.
+
+ .. change::
+ :tags: oracle
+ :tickets: 885
+
+ the Oracle dialect now features NUMBER which intends
+ to act justlike Oracle's NUMBER type. It is the primary
+ numeric type returned by table reflection and attempts
+ to return Decimal()/float/int based on the precision/scale
+ parameters.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ func.char_length is a generic function for LENGTH
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ ForeignKey() which includes onupdate=<value> will emit a
+ warning, not emit ON UPDATE CASCADE which is unsupported
+ by oracle
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ the keys() method of RowProxy() now returns the result
+ column names *normalized* to be SQLAlchemy case
+ insensitive names. This means they will be lower case for
+ case insensitive names, whereas the DBAPI would normally
+ return them as UPPERCASE names. This allows row keys() to
+ be compatible with further SQLAlchemy operations.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ using new dialect.initialize() feature to set up
+ version-dependent behavior.
+
+ .. change::
+ :tags: oracle
+ :tickets: 1125
+
+ using types.BigInteger with Oracle will generate
+ NUMBER(19)
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ "case sensitivity" feature will detect an all-lowercase
+ case-sensitive column name during reflect and add
+ "quote=True" to the generated Column, so that proper
+ quoting is maintained.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ the keys() method of RowProxy() now returns the result
+ column names *normalized* to be SQLAlchemy case
+ insensitive names. This means they will be lower case for
+ case insensitive names, whereas the DBAPI would normally
+ return them as UPPERCASE names. This allows row keys() to
+ be compatible with further SQLAlchemy operations.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ using new dialect.initialize() feature to set up
+ version-dependent behavior.
+
+ .. change::
+ :tags: firebird
+ :tickets:
+
+ "case sensitivity" feature will detect an all-lowercase
+ case-sensitive column name during reflect and add
+ "quote=True" to the generated Column, so that proper
+ quoting is maintained.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ MSSQL + Pyodbc + FreeTDS now works for the most part,
+ with possible exceptions regarding binary data as well as
+ unicode schema identifiers.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ the "has_window_funcs" flag is removed. LIMIT/OFFSET
+ usage will use ROW NUMBER as always, and if on an older
+ version of SQL Server, the operation fails. The behavior
+ is exactly the same except the error is raised by SQL
+ server instead of the dialect, and no flag setting is
+ required to enable it.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ the "auto_identity_insert" flag is removed. This feature
+ always takes effect when an INSERT statement overrides a
+ column that is known to have a sequence on it. As with
+ "has_window_funcs", if the underlying driver doesn't
+ support this, then you can't do this operation in any
+ case, so there's no point in having a flag.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ using new dialect.initialize() feature to set up
+ version-dependent behavior.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ removed references to sequence which is no longer used.
+ implicit identities in mssql work the same as implicit
+ sequences on any other dialects. Explicit sequences are
+ enabled through the use of "default=Sequence()". See
+ the MSSQL dialect documentation for more information.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ DATE, TIME and DATETIME types can now take optional storage_format
+ and regexp argument. storage_format can be used to store those types
+ using a custom string format. regexp allows to use a custom regular
+ expression to match string values from the database.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ Time and DateTime types now use by a default a stricter regular
+ expression to match strings from the database. Use the regexp
+ argument if you are using data stored in a legacy format.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ __legacy_microseconds__ on SQLite Time and DateTime types is not
+ supported anymore. You should use the storage_format argument
+ instead.
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ Date, Time and DateTime types are now stricter in what they accept as
+ bind parameters: Date type only accepts date objects (and datetime
+ ones, because they inherit from date), Time only accepts time
+ objects, and DateTime only accepts date and datetime objects.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 1016
+
+ Table() supports a keyword argument "sqlite_autoincrement", which
+ applies the SQLite keyword "AUTOINCREMENT" to the single integer
+ primary key column when generating DDL. Will prevent generation of
+ a separate PRIMARY KEY constraint.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ The construction of types within dialects has been totally
+ overhauled. Dialects now define publically available types
+ as UPPERCASE names exclusively, and internal implementation
+ types using underscore identifiers (i.e. are private).
+ The system by which types are expressed in SQL and DDL
+ has been moved to the compiler system. This has the
+ effect that there are much fewer type objects within
+ most dialects. A detailed document on this architecture
+ for dialect authors is in
+ lib/sqlalchemy/dialects/type_migration_guidelines.txt .
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ Types no longer make any guesses as to default
+ parameters. In particular, Numeric, Float, NUMERIC,
+ FLOAT, DECIMAL don't generate any length or scale unless
+ specified.
+
+ .. change::
+ :tags: types
+ :tickets: 1664
+
+ types.Binary is renamed to types.LargeBinary, it only
+ produces BLOB, BYTEA, or a similar "long binary" type.
+ New base BINARY and VARBINARY
+ types have been added to access these MySQL/MS-SQL specific
+ types in an agnostic way.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ String/Text/Unicode types now skip the unicode() check
+ on each result column value if the dialect has
+ detected the DBAPI as returning Python unicode objects
+ natively. This check is issued on first connect
+ using "SELECT CAST 'some text' AS VARCHAR(10)" or
+ equivalent, then checking if the returned object
+ is a Python unicode. This allows vast performance
+ increases for native-unicode DBAPIs, including
+ pysqlite/sqlite3, psycopg2, and pg8000.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ Most types result processors have been checked for possible speed
+ improvements. Specifically, the following generic types have been
+ optimized, resulting in varying speed improvements:
+ Unicode, PickleType, Interval, TypeDecorator, Binary.
+ Also the following dbapi-specific implementations have been improved:
+ Time, Date and DateTime on Sqlite, ARRAY on Postgresql,
+ Time on MySQL, Numeric(as_decimal=False) on MySQL, oursql and
+ pypostgresql, DateTime on cx_oracle and LOB-based types on cx_oracle.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ Reflection of types now returns the exact UPPERCASE
+ type within types.py, or the UPPERCASE type within
+ the dialect itself if the type is not a standard SQL
+ type. This means reflection now returns more accurate
+ information about reflected types.
+
+ .. change::
+ :tags: types
+ :tickets: 1511, 1109
+
+ Added a new Enum generic type. Enum is a schema-aware object
+ to support databases which require specific DDL in order to
+ use enum or equivalent; in the case of PG it handles the
+ details of `CREATE TYPE`, and on other databases without
+ native enum support will by generate VARCHAR + an inline CHECK
+ constraint to enforce the enum.
+
+ .. change::
+ :tags: types
+ :tickets: 1467
+
+ The Interval type includes a "native" flag which controls
+ if native INTERVAL types (postgresql + oracle) are selected
+ if available, or not. "day_precision" and "second_precision"
+ arguments are also added which propagate as appropriately
+ to these native types. Related to.
+
+ .. change::
+ :tags: types
+ :tickets: 1589
+
+ The Boolean type, when used on a backend that doesn't
+ have native boolean support, will generate a CHECK
+ constraint "col IN (0, 1)" along with the int/smallint-
+ based column type. This can be switched off if
+ desired with create_constraint=False.
+ Note that MySQL has no native boolean *or* CHECK constraint
+ support so this feature isn't available on that platform.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ PickleType now uses == for comparison of values when
+ mutable=True, unless the "comparator" argument with a
+ comparsion function is specified to the type. Objects
+ being pickled will be compared based on identity (which
+ defeats the purpose of mutable=True) if __eq__() is not
+ overridden or a comparison function is not provided.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ The default "precision" and "scale" arguments of Numeric
+ and Float have been removed and now default to None.
+ NUMERIC and FLOAT will be rendered with no numeric
+ arguments by default unless these values are provided.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ AbstractType.get_search_list() is removed - the games
+ that was used for are no longer necessary.
+
+ .. change::
+ :tags: types
+ :tickets: 1125
+
+ Added a generic BigInteger type, compiles to
+ BIGINT or NUMBER(19).
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ sqlsoup has been overhauled to explicitly support an 0.5 style
+ session, using autocommit=False, autoflush=True. Default
+ behavior of SQLSoup now requires the usual usage of commit()
+ and rollback(), which have been added to its interface. An
+ explcit Session or scoped_session can be passed to the
+ constructor, allowing these arguments to be overridden.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ sqlsoup db.<sometable>.update() and delete() now call
+ query(cls).update() and delete(), respectively.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ sqlsoup now has execute() and connection(), which call upon
+ the Session methods of those names, ensuring that the bind is
+ in terms of the SqlSoup object's bind.
+
+ .. change::
+ :tags: types
+ :tickets:
+
+ sqlsoup objects no longer have the 'query' attribute - it's
+ not needed for sqlsoup's usage paradigm and it gets in the
+ way of a column that is actually named 'query'.
+
+ .. change::
+ :tags: types
+ :tickets: 1259
+
+ The signature of the proxy_factory callable passed to
+ association_proxy is now (lazy_collection, creator,
+ value_attr, association_proxy), adding a fourth argument
+ that is the parent AssociationProxy argument. Allows
+ serializability and subclassing of the built in collections.
+
+ .. change::
+ :tags: types
+ :tickets: 1372
+
+ association_proxy now has basic comparator methods .any(),
+ .has(), .contains(), ==, !=, thanks to Scott Torborg.
--- /dev/null
+
+==============
+0.7 Changelog
+==============
+
+
+.. changelog::
+ :version: 0.7.10
+ :released:
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2583
+
+ Fixed Session accounting bug whereby replacing
+ a deleted object in the identity map with another
+ object of the same primary key would raise a
+ "conflicting state" error on rollback(),
+ if the replaced primary key were established either
+ via non-unitofwork-established INSERT statement
+ or by primary key switch of another instance.
+
+ .. change::
+ :tags: oracle, bug
+ :tickets: 2561
+
+ changed the list of cx_oracle types that are
+ excluded from the setinputsizes() step to only include
+ STRING and UNICODE; CLOB and NCLOB are removed. This
+ is to work around cx_oracle behavior which is broken
+ for the executemany() call. In 0.8, this same change
+ is applied however it is also configurable via the
+ exclude_setinputsizes argument.
+
+ .. change::
+ :tags: feature, mysql
+ :tickets: 2523
+
+ Added "raise_on_warnings" flag to OurSQL
+ dialect.
+
+ .. change::
+ :tags: feature, mysql
+ :tickets: 2554
+
+ Added "read_timeout" flag to MySQLdb
+ dialect.
+
+.. changelog::
+ :version: 0.7.9
+ :released: Mon Oct 01 2012
+
+ .. change::
+ :tags: orm, bug
+ :tickets:
+
+ Fixed bug mostly local to new
+ AbstractConcreteBase helper where the "type"
+ attribute from the superclass would not
+ be overridden on the subclass to produce the
+ "reserved for base" error message, instead placing
+ a do-nothing attribute there. This was inconsistent
+ vs. using ConcreteBase as well as all the behavior
+ of classical concrete mappings, where the "type"
+ column from the polymorphic base would be explicitly
+ disabled on subclasses, unless overridden
+ explicitly.
+
+ .. change::
+ :tags: orm, bug
+ :tickets:
+
+ A warning is emitted when lazy='dynamic'
+ is combined with uselist=False. This is an
+ exception raise in 0.8.
+
+ .. change::
+ :tags: orm, bug
+ :tickets:
+
+ Fixed bug whereby user error in related-object
+ assignment could cause recursion overflow if the
+ assignment triggered a backref of the same name
+ as a bi-directional attribute on the incorrect
+ class to the same target. An informative
+ error is raised now.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2539
+
+ Fixed bug where incorrect type information
+ would be passed when the ORM would bind the
+ "version" column, when using the "version" feature.
+ Tests courtesy Daniel Miller.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2566
+
+ Extra logic has been added to the "flush"
+ that occurs within Session.commit(), such that the
+ extra state added by an after_flush() or
+ after_flush_postexec() hook is also flushed in a
+ subsequent flush, before the "commit" completes.
+ Subsequent calls to flush() will continue until
+ the after_flush hooks stop adding new state.
+ An "overflow" counter of 100 is also in place,
+ in the event of a broken after_flush() hook
+ adding new content each time.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2571
+
+ Fixed the DropIndex construct to support
+ an Index associated with a Table in a remote
+ schema.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2574
+
+ Fixed bug in over() construct whereby
+ passing an empty list for either partition_by
+ or order_by, as opposed to None, would fail
+ to generate correctly.
+ Courtesy Gunnlaugur Þór Briem.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2521
+
+ Fixed CTE bug whereby positional
+ bound parameters present in the CTEs themselves
+ would corrupt the overall ordering of
+ bound parameters. This primarily
+ affected SQL Server as the platform with
+ positional binds + CTE support.
+
+ .. change::
+ :tags: bug, sql
+ :tickets:
+
+ Fixed more un-intuitivenesses in CTEs
+ which prevented referring to a CTE in a union
+ of itself without it being aliased.
+ CTEs now render uniquely
+ on name, rendering the outermost CTE of a given
+ name only - all other references are rendered
+ just as the name. This even includes other
+ CTE/SELECTs that refer to different versions
+ of the same CTE object, such as a SELECT
+ or a UNION ALL of that SELECT. We are
+ somewhat loosening the usual link between object
+ identity and lexical identity in this case.
+ A true name conflict between two unrelated
+ CTEs now raises an error.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2512
+
+ quoting is applied to the column names
+ inside the WITH RECURSIVE clause of a
+ common table expression according to the
+ quoting rules for the originating Column.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2518
+
+ Fixed regression introduced in 0.7.6
+ whereby the FROM list of a SELECT statement
+ could be incorrect in certain "clone+replace"
+ scenarios.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2552
+
+ Fixed bug whereby usage of a UNION
+ or similar inside of an embedded subquery
+ would interfere with result-column targeting,
+ in the case that a result-column had the same
+ ultimate name as a name inside the embedded
+ UNION.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2558
+
+ Fixed a regression since 0.6 regarding
+ result-row targeting. It should be possible
+ to use a select() statement with string
+ based columns in it, that is
+ select(['id', 'name']).select_from('mytable'),
+ and have this statement be targetable by
+ Column objects with those names; this is the
+ mechanism by which
+ query(MyClass).from_statement(some_statement)
+ works. At some point the specific case of
+ using select(['id']), which is equivalent to
+ select([literal_column('id')]), stopped working
+ here, so this has been re-instated and of
+ course tested.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2544
+
+ Added missing operators is_(), isnot()
+ to the ColumnOperators base, so that these long-available
+ operators are present as methods like all
+ the other operators.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2522
+
+ Fixed bug whereby
+ a disconnect detect + dispose that occurs
+ when the QueuePool has threads waiting
+ for connections would leave those
+ threads waiting for the duration of
+ the timeout on the old pool (or indefinitely
+ if timeout was disabled). The fix
+ now notifies those waiters with a special
+ exception case and has them move onto
+ the new pool.
+
+ .. change::
+ :tags: engine, feature
+ :tickets: 2516
+
+ Dramatic improvement in memory
+ usage of the event system; instance-level
+ collections are no longer created for a
+ particular type of event until
+ instance-level listeners are established
+ for that event.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2529
+
+ Added gaerdbms import to mysql/__init__.py,
+ the absense of which was preventing the new
+ GAE dialect from being loaded.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2553
+
+ Fixed cextension bug whereby the
+ "ambiguous column error" would fail to
+ function properly if the given index were
+ a Column object and not a string.
+ Note there are still some column-targeting
+ issues here which are fixed in 0.8.
+
+ .. change::
+ :tags: engine, bug
+ :tickets:
+
+ Fixed the repr() of Enum to include
+ the "name" and "native_enum" flags. Helps
+ Alembic autogenerate.
+
+ .. change::
+ :tags: sqlite, bug
+ :tickets: 2568
+
+ Adjusted a very old bugfix which attempted
+ to work around a SQLite issue that itself was
+ "fixed" as of sqlite 3.6.14, regarding quotes
+ surrounding a table name when using
+ the "foreign_key_list" pragma. The fix has been
+ adjusted to not interfere with quotes that
+ are *actually in the name* of a column or table,
+ to as much a degree as possible; sqlite still
+ doesn't return the correct result for foreign_key_list()
+ if the target table actually has quotes surrounding
+ its name, as *part* of its name (i.e. """mytable""").
+
+ .. change::
+ :tags: sqlite, bug
+ :tickets: 2265
+
+ Adjusted column default reflection code to
+ convert non-string values to string, to accommodate
+ old SQLite versions that don't deliver
+ default info as a string.
+
+ .. change::
+ :tags: sqlite, feature
+ :tickets:
+
+ Added support for the localtimestamp()
+ SQL function implemented in SQLite, courtesy
+ Richard Mitchell.
+
+ .. change::
+ :tags: postgresql, bug
+ :tickets: 2531
+
+ Columns in reflected primary key constraint
+ are now returned in the order in which the constraint
+ itself defines them, rather than how the table
+ orders them. Courtesy Gunnlaugur Þór Briem..
+
+ .. change::
+ :tags: postgresql, bug
+ :tickets: 2570
+
+ Added 'terminating connection' to the list
+ of messages we use to detect a disconnect with PG, which
+ appears to be present in some versions when the server
+ is restarted.
+
+ .. change::
+ :tags: bug, mysql
+ :tickets:
+
+ Updated mysqlconnector interface to use
+ updated "client flag" and "charset" APIs,
+ courtesy David McNelis.
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2538
+
+ Fixed compiler bug whereby using a correlated
+ subquery within an ORDER BY would fail to render correctly
+ if the stament also used LIMIT/OFFSET, due to mis-rendering
+ within the ROW_NUMBER() OVER clause. Fix courtesy
+ sayap
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2545
+
+ Fixed compiler bug whereby a given
+ select() would be modified if it had an "offset"
+ attribute, causing the construct to not compile
+ correctly a second time.
+
+ .. change::
+ :tags: mssql, bug
+ :tickets:
+
+ Fixed bug where reflection of primary key constraint
+ would double up columns if the same constraint/table
+ existed in multiple schemas.
+
+.. changelog::
+ :version: 0.7.8
+ :released: Sat Jun 16 2012
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2480
+
+ Fixed bug whereby subqueryload() from
+ a polymorphic mapping to a target would incur
+ a new invocation of the query for each
+ distinct class encountered in the polymorphic
+ result.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2491, 1892
+
+ Fixed bug in declarative
+ whereby the precedence of columns
+ in a joined-table, composite
+ column (typically for id) would fail to
+ be correct if the columns contained
+ names distinct from their attribute
+ names. This would cause things like
+ primaryjoin conditions made against the
+ entity attributes to be incorrect. Related
+ to as this was supposed
+ to be part of that, this is.
+
+ .. change::
+ :tags: orm, feature
+ :tickets:
+
+ The 'objects' argument to
+ flush() is no longer deprecated, as some
+ valid use cases have been identified.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2508
+
+ Fixed identity_key() function which
+ was not accepting a scalar argument
+ for the identity. .
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2497
+
+ Fixed bug whereby populate_existing
+ option would not propagate to subquery
+ eager loaders. .
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2499
+
+ added BIGINT to types.__all__,
+ BIGINT, BINARY, VARBINARY to sqlalchemy
+ module namespace, plus test to ensure
+ this breakage doesn't occur again.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2490
+
+ Repaired common table expression
+ rendering to function correctly when the
+ SELECT statement contains UNION or other
+ compound expressions, courtesy btbuilder.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2482
+
+ Fixed bug whereby append_column()
+ wouldn't function correctly on a cloned
+ select() construct, courtesy
+ Gunnlaugur Þór Briem.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2489
+
+ Fixed memory leak in C version of
+ result proxy whereby DBAPIs which don't deliver
+ pure Python tuples for result rows would
+ fail to decrement refcounts correctly.
+ The most prominently affected DBAPI
+ is pyodbc.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2503
+
+ Fixed bug affecting Py3K whereby
+ string positional parameters passed to
+ engine/connection execute() would fail to be
+ interpreted correctly, due to __iter__
+ being present on Py3K string..
+
+ .. change::
+ :tags: postgresql, bug
+ :tickets: 2510
+
+ removed unnecessary table clause when
+ reflecting enums,. Courtesy
+ Gunnlaugur Þór Briem.
+
+ .. change::
+ :tags: oracle, bug
+ :tickets: 2483
+
+ Added ROWID to oracle.*.
+
+ .. change::
+ :tags: feature, mysql
+ :tickets: 2484
+
+ Added a new dialect for Google App
+ Engine. Courtesy Richie Foreman.
+
+.. changelog::
+ :version: 0.7.7
+ :released: Sat May 05 2012
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2477
+
+ Fixed issue in unit of work
+ whereby setting a non-None self-referential
+ many-to-one relationship to None
+ would fail to persist the change if the
+ former value was not already loaded..
+
+ .. change::
+ :tags: orm, feature
+ :tickets: 2443
+
+ Added prefix_with() method
+ to Query, calls upon select().prefix_with()
+ to allow placement of MySQL SELECT
+ directives in statements. Courtesy
+ Diana Clarke
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2409
+
+ Fixed bug in 0.7.6 introduced by whereby column_mapped_collection
+ used against columns that were mapped as
+ joins or other indirect selectables
+ would fail to function.
+
+ .. change::
+ :tags: orm, feature
+ :tickets:
+
+ Added new flag to @validates
+ include_removes. When True, collection
+ remove and attribute del events
+ will also be sent to the validation function,
+ which accepts an additional argument
+ "is_remove" when this flag is used.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2449
+
+ Fixed bug whereby polymorphic_on
+ column that's not otherwise mapped on the
+ class would be incorrectly included
+ in a merge() operation, raising an error.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2453
+
+ Fixed bug in expression annotation
+ mechanics which could lead to incorrect
+ rendering of SELECT statements with aliases
+ and joins, particularly when using
+ column_property().
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2454
+
+ Fixed bug which would prevent
+ OrderingList from being pickleable. Courtesy Jeff Dairiki
+
+ .. change::
+ :tags: orm, bug
+ :tickets:
+
+ Fixed bug in relationship comparisons
+ whereby calling unimplemented methods like
+ SomeClass.somerelationship.like() would
+ produce a recursion overflow, instead
+ of NotImplementedError.
+
+ .. change::
+ :tags: bug, sql
+ :tickets:
+
+ Removed warning when Index is created
+ with no columns; while this might not be what
+ the user intended, it is a valid use case
+ as an Index could be a placeholder for just an
+ index of a certain name.
+
+ .. change::
+ :tags: feature, sql
+ :tickets:
+
+ Added new connection event
+ dbapi_error(). Is called for all DBAPI-level
+ errors passing the original DBAPI exception
+ before SQLAlchemy modifies the state
+ of the cursor.
+
+ .. change::
+ :tags: bug, sql
+ :tickets:
+
+ If conn.begin() fails when calling
+ "with engine.begin()", the newly acquired
+ Connection is closed explicitly before
+ propagating the exception onward normally.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2474
+
+ Add BINARY, VARBINARY to types.__all__.
+
+ .. change::
+ :tags: mssql, feature
+ :tickets:
+
+ Added interim create_engine flag
+ supports_unicode_binds to PyODBC dialect,
+ to force whether or not the dialect
+ passes Python unicode literals to PyODBC
+ or not.
+
+ .. change::
+ :tags: mssql, bug
+ :tickets:
+
+ Repaired the use_scope_identity
+ create_engine() flag when using the pyodbc
+ dialect. Previously this flag would be
+ ignored if set to False. When set to False,
+ you'll get "SELECT @@identity" after each
+ INSERT to get at the last inserted ID,
+ for those tables which have "implicit_returning"
+ set to False.
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2468
+
+ UPDATE..FROM syntax with SQL Server
+ requires that the updated table be present
+ in the FROM clause when an alias of that
+ table is also present in the FROM clause.
+ The updated table is now always present
+ in the FROM, when FROM is present
+ in the first place. Courtesy sayap.
+
+ .. change::
+ :tags: postgresql, feature
+ :tickets: 2445
+
+ Added new for_update/with_lockmode()
+ options for Postgresql: for_update="read"/
+ with_lockmode("read"),
+ for_update="read_nowait"/
+ with_lockmode("read_nowait").
+ These emit "FOR SHARE" and "FOR SHARE NOWAIT",
+ respectively. Courtesy Diana Clarke
+
+ .. change::
+ :tags: postgresql, bug
+ :tickets: 2473
+
+ removed unnecessary table clause
+ when reflecting domains.
+
+ .. change::
+ :tags: bug, mysql
+ :tickets: 2460
+
+ Fixed bug whereby column name inside
+ of "KEY" clause for autoincrement composite
+ column with InnoDB would double quote a
+ name that's a reserved word. Courtesy Jeff
+ Dairiki.
+
+ .. change::
+ :tags: bug, mysql
+ :tickets:
+
+ Fixed bug whereby get_view_names() for
+ "information_schema" schema would fail
+ to retrieve views marked as "SYSTEM VIEW".
+ courtesy Matthew Turland.
+
+ .. change::
+ :tags: bug, mysql
+ :tickets: 2467
+
+ Fixed bug whereby if cast() is used
+ on a SQL expression whose type is not supported
+ by cast() and therefore CAST isn't rendered by
+ the dialect, the order of evaluation could change
+ if the casted expression required that it be
+ grouped; grouping is now applied to those
+ expressions.
+
+ .. change::
+ :tags: sqlite, feature
+ :tickets: 2475
+
+ Added SQLite execution option
+ "sqlite_raw_colnames=True", will bypass
+ attempts to remove "." from column names
+ returned by SQLite cursor.description.
+
+ .. change::
+ :tags: sqlite, bug
+ :tickets: 2525
+
+ When the primary key column of a Table
+ is replaced, such as via extend_existing,
+ the "auto increment" column used by insert()
+ constructs is reset. Previously it would
+ remain referring to the previous primary
+ key column.
+
+.. changelog::
+ :version: 0.7.6
+ :released: Wed Mar 14 2012
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2424
+
+ Fixed event registration bug
+ which would primarily show up as
+ events not being registered with
+ sessionmaker() instances created
+ after the event was associated
+ with the Session class.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2425
+
+ Fixed bug whereby a primaryjoin
+ condition with a "literal" in it would
+ raise an error on compile with certain
+ kinds of deeply nested expressions
+ which also needed to render the same
+ bound parameter name more than once.
+
+ .. change::
+ :tags: orm, feature
+ :tickets:
+
+ Added "no_autoflush" context
+ manager to Session, used with with:
+ will temporarily disable autoflush.
+
+ .. change::
+ :tags: orm, feature
+ :tickets: 1859
+
+ Added cte() method to Query,
+ invokes common table expression support
+ from the Core (see below).
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2403
+
+ Removed the check for number of
+ rows affected when doing a multi-delete
+ against mapped objects. If an ON DELETE
+ CASCADE exists between two rows, we can't
+ get an accurate rowcount from the DBAPI;
+ this particular count is not supported
+ on most DBAPIs in any case, MySQLdb
+ is the notable case where it is.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2409
+
+ Fixed bug whereby objects using
+ attribute_mapped_collection or
+ column_mapped_collection could not be
+ pickled.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2406
+
+ Fixed bug whereby MappedCollection
+ would not get the appropriate collection
+ instrumentation if it were only used
+ in a custom subclass that used
+ @collection.internally_instrumented.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2419
+
+ Fixed bug whereby SQL adaption mechanics
+ would fail in a very nested scenario involving
+ joined-inheritance, joinedload(), limit(), and a
+ derived function in the columns clause.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2417
+
+ Fixed the repr() for CascadeOptions to
+ include refresh-expire. Also reworked
+ CascadeOptions to be a <frozenset>.
+
+ .. change::
+ :tags: orm, feature
+ :tickets: 2400
+
+ Added the ability to query for
+ Table-bound column names when using
+ query(sometable).filter_by(colname=value).
+
+ .. change::
+ :tags: orm, bug
+ :tickets:
+
+ Improved the "declarative reflection"
+ example to support single-table inheritance,
+ multiple calls to prepare(), tables that
+ are present in alternate schemas,
+ establishing only a subset of classes
+ as reflected.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2390
+
+ Scaled back the test applied within
+ flush() to check for UPDATE against partially
+ NULL PK within one table to only actually
+ happen if there's really an UPDATE to occur.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2352
+
+ Fixed bug whereby if a method name
+ conflicted with a column name, a
+ TypeError would be raised when the mapper
+ tried to inspect the __get__() method
+ on the method object.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2427
+
+ Fixed memory leak in core which would
+ occur when C extensions were used with
+ particular types of result fetches,
+ in particular when orm query.count()
+ were called.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2398
+
+ Fixed issue whereby attribute-based
+ column access on a row would raise
+ AttributeError with non-C version,
+ NoSuchColumnError with C version. Now
+ raises AttributeError in both cases.
+
+ .. change::
+ :tags: feature, sql
+ :tickets: 1859
+
+ Added support for SQL standard
+ common table expressions (CTE), allowing
+ SELECT objects as the CTE source (DML
+ not yet supported). This is invoked via
+ the cte() method on any select() construct.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2392
+
+ Added support for using the .key
+ of a Column as a string identifier in a
+ result set row. The .key is currently
+ listed as an "alternate" name for a column,
+ and is superseded by the name of a column
+ which has that key value as its regular name.
+ For the next major release
+ of SQLAlchemy we may reverse this precedence
+ so that .key takes precedence, but this
+ is not decided on yet.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2413
+
+ A warning is emitted when a not-present
+ column is stated in the values() clause
+ of an insert() or update() construct.
+ Will move to an exception in 0.8.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2396
+
+ A significant change to how labeling
+ is applied to columns in SELECT statements
+ allows "truncated" labels, that is label names
+ that are generated in Python which exceed
+ the maximum identifier length (note this is
+ configurable via label_length on create_engine()),
+ to be properly referenced when rendered inside
+ of a subquery, as well as to be present
+ in a result set row using their original
+ in-Python names.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2402
+
+ Fixed bug in new "autoload_replace" flag
+ which would fail to preserve the primary
+ key constraint of the reflected table.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2380
+
+ Index will raise when arguments passed
+ cannot be interpreted as columns or expressions.
+ Will warn when Index is created
+ with no columns at all.
+
+ .. change::
+ :tags: engine, feature
+ :tickets: 2407
+
+ Added "no_parameters=True" execution
+ option for connections. If no parameters
+ are present, will pass the statement
+ as cursor.execute(statement), thereby invoking
+ the DBAPIs behavior when no parameter collection
+ is present; for psycopg2 and mysql-python, this
+ means not interpreting % signs in the string.
+ This only occurs with this option, and not
+ just if the param list is blank, as otherwise
+ this would produce inconsistent behavior
+ of SQL expressions that normally escape percent
+ signs (and while compiling, can't know ahead of
+ time if parameters will be present in
+ some cases).
+
+ .. change::
+ :tags: engine, bug
+ :tickets:
+
+ Added execution_options() call to
+ MockConnection (i.e., that used with
+ strategy="mock") which acts as a pass through
+ for arguments.
+
+ .. change::
+ :tags: engine, feature
+ :tickets: 2378
+
+ Added pool_reset_on_return argument
+ to create_engine, allows control over
+ "connection return" behavior. Also added
+ new arguments 'rollback', 'commit', None
+ to pool.reset_on_return to allow more control
+ over connection return activity.
+
+ .. change::
+ :tags: engine, feature
+ :tickets:
+
+ Added some decent context managers
+ to Engine, Connection:
+
+ with engine.begin() as conn:
+ <work with conn in a transaction>
+
+ and:
+
+ with engine.connect() as conn:
+ <work with conn>
+
+ Both close out the connection when done,
+ commit or rollback transaction with errors
+ on engine.begin().
+
+ .. change::
+ :tags: sqlite, bug
+ :tickets: 2432
+
+ Fixed bug in C extensions whereby
+ string format would not be applied to a
+ Numeric value returned as integer; this
+ affected primarily SQLite which does
+ not maintain numeric scale settings.
+
+ .. change::
+ :tags: mssql, feature
+ :tickets: 2430
+
+ Added support for MSSQL INSERT,
+ UPDATE, and DELETE table hints, using
+ new with_hint() method on UpdateBase.
+
+ .. change::
+ :tags: feature, mysql
+ :tickets: 2386
+
+ Added support for MySQL index and
+ primary key constraint types
+ (i.e. USING) via new mysql_using parameter
+ to Index and PrimaryKeyConstraint,
+ courtesy Diana Clarke.
+
+ .. change::
+ :tags: feature, mysql
+ :tickets: 2394
+
+ Added support for the "isolation_level"
+ parameter to all MySQL dialects. Thanks
+ to mu_mind for the patch here.
+
+ .. change::
+ :tags: oracle, feature
+ :tickets: 2399
+
+ Added a new create_engine() flag
+ coerce_to_decimal=False, disables the precision
+ numeric handling which can add lots of overhead
+ by converting all numeric values to
+ Decimal.
+
+ .. change::
+ :tags: oracle, bug
+ :tickets: 2401
+
+ Added missing compilation support for
+ LONG
+
+ .. change::
+ :tags: oracle, bug
+ :tickets: 2435
+
+ Added 'LEVEL' to the list of reserved
+ words for Oracle.
+
+ .. change::
+ :tags: examples, bug
+ :tickets:
+
+ Altered _params_from_query() function
+ in Beaker example to pull bindparams from the
+ fully compiled statement, as a quick means
+ to get everything including subqueries in the
+ columns clause, etc.
+
+.. changelog::
+ :version: 0.7.5
+ :released: Sat Jan 28 2012
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2389
+
+ Fixed issue where modified session state
+ established after a failed flush would be committed
+ as part of the subsequent transaction that
+ begins automatically after manual call
+ to rollback(). The state of the session is
+ checked within rollback(), and if new state
+ is present, a warning is emitted and
+ restore_snapshot() is called a second time,
+ discarding those changes.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2345
+
+ Fixed regression from 0.7.4 whereby
+ using an already instrumented column from a
+ superclass as "polymorphic_on" failed to resolve
+ the underlying Column.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2370
+
+ Raise an exception if xyzload_all() is
+ used inappropriately with two non-connected
+ relationships.
+
+ .. change::
+ :tags: orm, feature
+ :tickets:
+
+ Added "class_registry" argument to
+ declarative_base(). Allows two or more declarative
+ bases to share the same registry of class names.
+
+ .. change::
+ :tags: orm, feature
+ :tickets:
+
+ query.filter() accepts multiple
+ criteria which will join via AND, i.e.
+ query.filter(x==y, z>q, ...)
+
+ .. change::
+ :tags: orm, feature
+ :tickets: 2351
+
+ Added new capability to relationship
+ loader options to allow "default" loader strategies.
+ Pass '*' to any of joinedload(), lazyload(),
+ subqueryload(), or noload() and that becomes the
+ loader strategy used for all relationships,
+ except for those explicitly stated in the
+ Query. Thanks to up-and-coming contributor
+ Kent Bower for an exhaustive and well
+ written test suite !
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2367
+
+ Fixed bug whereby event.listen(SomeClass)
+ forced an entirely unnecessary compile of the
+ mapper, making events very hard to set up
+ at module import time (nobody noticed this ??)
+
+ .. change::
+ :tags: orm, bug
+ :tickets:
+
+ Fixed bug whereby hybrid_property didn't
+ work as a kw arg in any(), has().
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed regression from 0.6 whereby if
+ "load_on_pending" relationship() flag were used
+ where a non-"get()" lazy clause needed to be
+ emitted on a pending object, it would fail
+ to load.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2371
+
+ ensure pickleability of all ORM exceptions
+ for multiprocessing compatibility.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2353
+
+ implemented standard "can't set attribute" /
+ "can't delete attribute" AttributeError when
+ setattr/delattr used on a hybrid that doesn't
+ define fset or fdel.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2362
+
+ Fixed bug where unpickled object didn't
+ have enough of its state set up to work
+ correctly within the unpickle() event established
+ by the mutable object extension, if the object
+ needed ORM attribute access within
+ __eq__() or similar.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2374
+
+ Fixed bug where "merge" cascade could
+ mis-interpret an unloaded attribute, if the
+ load_on_pending flag were used with
+ relationship(). Thanks to Kent Bower
+ for tests.
+
+ .. change::
+ :tags: orm, feature
+ :tickets: 2356
+
+ New declarative reflection example
+ added, illustrates how best to mix table reflection
+ with declarative as well as uses some new features
+ from.
+
+ .. change::
+ :tags: feature, sql
+ :tickets: 2356
+
+ New reflection feature "autoload_replace";
+ when set to False on Table, the Table can be autoloaded
+ without existing columns being replaced. Allows
+ more flexible chains of Table construction/reflection
+ to be constructed, including that it helps with
+ combining Declarative with table reflection.
+ See the new example on the wiki.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2356
+
+ Improved the API for add_column() such that
+ if the same column is added to its own table,
+ an error is not raised and the constraints
+ don't get doubled up. Also helps with some
+ reflection/declarative patterns.
+
+ .. change::
+ :tags: feature, sql
+ :tickets:
+
+ Added "false()" and "true()" expression
+ constructs to sqlalchemy.sql namespace, though
+ not part of __all__ as of yet.
+
+ .. change::
+ :tags: feature, sql
+ :tickets: 2361
+
+ Dialect-specific compilers now raise
+ CompileException for all type/statement compilation
+ issues, instead of InvalidRequestError or ArgumentError.
+ The DDL for CREATE TABLE will re-raise
+ CompileExceptions to include table/column information
+ for the problematic column.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2381
+
+ Fixed issue where the "required" exception
+ would not be raised for bindparam() with required=True,
+ if the statement were given no parameters at all.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2371
+
+ Added __reduce__ to StatementError,
+ DBAPIError, column errors so that exceptions
+ are pickleable, as when using multiprocessing.
+ However, not
+ all DBAPIs support this yet, such as
+ psycopg2.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2382
+
+ Improved error messages when a non-string
+ or invalid string is passed to any of the
+ date/time processors used by SQLite, including
+ C and Python versions.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2377
+
+ Fixed bug whereby a table-bound Column
+ object named "<a>_<b>" which matched a column
+ labeled as "<tablename>_<colname>" could match
+ inappropriately when targeting in a result
+ set row.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2384
+
+ Fixed bug in "mock" strategy whereby
+ correct DDL visit method wasn't called, resulting
+ in "CREATE/DROP SEQUENCE" statements being
+ duplicated
+
+ .. change::
+ :tags: sqlite, bug
+ :tickets: 2364
+
+ the "name" of an FK constraint in SQLite
+ is reflected as "None", not "0" or other
+ integer value.
+ SQLite does not appear to support constraint
+ naming in any case.
+
+ .. change::
+ :tags: sqlite, bug
+ :tickets: 2368
+
+ sql.false() and sql.true() compile to
+ 0 and 1, respectively in sqlite
+
+ .. change::
+ :tags: sqlite, bug
+ :tickets:
+
+ removed an erroneous "raise" in the
+ SQLite dialect when getting table names
+ and view names, where logic is in place
+ to fall back to an older version of
+ SQLite that doesn't have the
+ "sqlite_temp_master" table.
+
+ .. change::
+ :tags: bug, mysql
+ :tickets: 2376
+
+ fixed regexp that filters out warnings
+ for non-reflected "PARTITION" directives,
+ thanks to George Reilly
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2340
+
+ Adjusted the regexp used in the
+ mssql.TIME type to ensure only six digits
+ are received for the "microseconds" portion
+ of the value, which is expected by
+ Python's datetime.time(). Note that
+ support for sending microseconds doesn't
+ seem to be possible yet with pyodbc
+ at least.
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2347
+
+ Dropped the "30 char" limit on pymssql,
+ based on reports that it's doing things
+ better these days. pymssql hasn't been
+ well tested and as the DBAPI is in flux
+ it's still not clear what the status
+ is on this driver and how SQLAlchemy's
+ implementation should adapt.
+
+ .. change::
+ :tags: oracle, bug
+ :tickets: 2388
+
+ Added ORA-03135 to the never ending
+ list of oracle "connection lost" errors
+
+ .. change::
+ :tags: core, bug
+ :tickets: 2379
+
+ Changed LRUCache, used by the mapper
+ to cache INSERT/UPDATE/DELETE statements,
+ to use an incrementing counter instead
+ of a timestamp to track entries, for greater
+ reliability versus using time.time(), which
+ can cause test failures on some platforms.
+
+ .. change::
+ :tags: core, bug
+ :tickets: 2383
+
+ Added a boolean check for the "finalize"
+ function within the pool connection proxy's
+ weakref callback before calling it, so that a
+ warning isn't emitted that this function is None
+ when the application is exiting and gc has
+ removed the function from the module before the
+ weakref callback was invoked.
+
+ .. change::
+ :tags: bug, py3k
+ :tickets: 2348
+
+ Fixed inappropriate usage of util.py3k
+ flag and renamed it to util.py3k_warning, since
+ this flag is intended to detect the -3 flag
+ series of import restrictions only.
+
+ .. change::
+ :tags: examples, feature
+ :tickets: 2313
+
+ Simplified the versioning example
+ a bit to use a declarative mixin as well
+ as an event listener, instead of a metaclass +
+ SessionExtension.
+
+ .. change::
+ :tags: examples, bug
+ :tickets: 2346
+
+ Fixed large_collection.py to close the
+ session before dropping tables.
+
+.. changelog::
+ :version: 0.7.4
+ :released: Fri Dec 09 2011
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2315
+
+ Fixed backref behavior when "popping" the
+ value off of a many-to-one in response to
+ a removal from a stale one-to-many - the operation
+ is skipped, since the many-to-one has since
+ been updated.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2264
+
+ After some years of not doing this, added
+ more granularity to the "is X a parent of Y"
+ functionality, which is used when determining
+ if the FK on "Y" needs to be "nulled out" as well
+ as if "Y" should be deleted with delete-orphan
+ cascade. The test now takes into account the
+ Python identity of the parent as well its identity
+ key, to see if the last known parent of Y is
+ definitely X. If a decision
+ can't be made, a StaleDataError is raised. The
+ conditions where this error is raised are fairly
+ rare, requiring that the previous parent was
+ garbage collected, and previously
+ could very well inappropriately update/delete
+ a record that's since moved onto a new parent,
+ though there may be some cases where
+ "silent success" occurred previously that will now
+ raise in the face of ambiguity.
+ Expiring "Y" resets the "parent" tracker, meaning
+ X.remove(Y) could then end up deleting Y even
+ if X is stale, but this is the same behavior
+ as before; it's advised to expire X also in that
+ case.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2310
+
+ fixed inappropriate evaluation of user-mapped
+ object in a boolean context within query.get(). Also in 0.6.9.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2304
+
+ Added missing comma to PASSIVE_RETURN_NEVER_SET
+ symbol
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 1776
+
+ Cls.column.collate("some collation") now
+ works. Also in 0.6.9
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2309
+
+ the value of a composite attribute is now
+ expired after an insert or update operation, instead
+ of regenerated in place. This ensures that a
+ column value which is expired within a flush
+ will be loaded first, before the composite
+ is regenerated using that value.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2309, 2308
+
+ The fix in also emits the
+ "refresh" event when the composite value is
+ loaded on access, even if all column
+ values were already present, as is appropriate.
+ This fixes the "mutable" extension which relies
+ upon the "load" event to ensure the _parents
+ dictionary is up to date, fixes.
+ Thanks to Scott Torborg for the test case here.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2312
+
+ Fixed bug whereby a subclass of a subclass
+ using concrete inheritance in conjunction with
+ the new ConcreteBase or AbstractConcreteBase
+ would fail to apply the subclasses deeper than
+ one level to the "polymorphic loader" of each
+ base
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2312
+
+ Fixed bug whereby a subclass of a subclass
+ using the new AbstractConcreteBase would fail
+ to acquire the correct "base_mapper" attribute
+ when the "base" mapper was generated, thereby
+ causing failures later on.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2316
+
+ Fixed bug whereby column_property() created
+ against ORM-level column could be treated as
+ a distinct entity when producing certain
+ kinds of joined-inh joins.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2297
+
+ Fixed the error formatting raised when
+ a tuple is inadvertently passed to session.query(). Also in 0.6.9.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2328
+
+ Calls to query.join() to a single-table
+ inheritance subclass are now tracked, and
+ are used to eliminate the additional WHERE..
+ IN criterion normally tacked on with single
+ table inheritance, since the join should
+ accommodate it. This allows OUTER JOIN
+ to a single table subclass to produce
+ the correct results, and overall will produce
+ fewer WHERE criterion when dealing with
+ single table inheritance joins.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2339
+
+ __table_args__ can now be passed as
+ an empty tuple as well as an empty dict.. Thanks to Fayaz Yusuf Khan
+ for the patch.
+
+ .. change::
+ :tags: orm, bug
+ :tickets: 2325
+
+ Updated warning message when setting
+ delete-orphan without delete to no longer
+ refer to 0.6, as we never got around to
+ upgrading this to an exception. Ideally
+ this might be better as an exception but
+ it's not critical either way.
+
+ .. change::
+ :tags: orm, feature
+ :tickets: 2345, 2238
+
+ polymorphic_on now accepts many
+ new kinds of values:
+
+ - standalone expressions that aren't
+ otherwise mapped
+ - column_property() objects
+ - string names of any column_property()
+ or attribute name of a mapped Column
+
+ The docs include an example using
+ the case() construct, which is likely to be
+ a common constructed used here. and part of
+
+ Standalone expressions in polymorphic_on
+ propagate to single-table inheritance
+ subclasses so that they are used in the
+ WHERE /JOIN clause to limit rows to that
+ subclass as is the usual behavior.
+
+ .. change::
+ :tags: orm, feature
+ :tickets: 2301
+
+ IdentitySet supports the - operator
+ as the same as difference(), handy when dealing
+ with Session.dirty etc.
+
+ .. change::
+ :tags: orm, feature
+ :tickets:
+
+ Added new value for Column autoincrement
+ called "ignore_fk", can be used to force autoincrement
+ on a column that's still part of a ForeignKeyConstraint.
+ New example in the relationship docs illustrates
+ its use.
+
+ .. change::
+ :tags: orm, bug
+ :tickets:
+
+ Fixed bug in get_history() when referring
+ to a composite attribute that has no value;
+ added coverage for get_history() regarding
+ composites which is otherwise just a userland
+ function.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2316, 2261
+
+ related to, made some
+ adjustments to the change from
+ regarding the "from" list on a select(). The
+ _froms collection is no longer memoized, as this
+ simplifies various use cases and removes the
+ need for a "warning" if a column is attached
+ to a table after it was already used in an
+ expression - the select() construct will now
+ always produce the correct expression.
+ There's probably no real-world
+ performance hit here; select() objects are
+ almost always made ad-hoc, and systems that
+ wish to optimize the re-use of a select()
+ would be using the "compiled_cache" feature.
+ A hit which would occur when calling select.bind
+ has been reduced, but the vast majority
+ of users shouldn't be using "bound metadata"
+ anyway :).
+
+ .. change::
+ :tags: feature, sql
+ :tickets: 2166, 1944
+
+ The update() construct can now accommodate
+ multiple tables in the WHERE clause, which will
+ render an "UPDATE..FROM" construct, recognized by
+ Postgresql and MSSQL. When compiled on MySQL,
+ will instead generate "UPDATE t1, t2, ..". MySQL
+ additionally can render against multiple tables in the
+ SET clause, if Column objects are used as keys
+ in the "values" parameter or generative method.
+
+ .. change::
+ :tags: feature, sql
+ :tickets: 77
+
+ Added accessor to types called "python_type",
+ returns the rudimentary Python type object
+ for a particular TypeEngine instance, if known,
+ else raises NotImplementedError.
+
+ .. change::
+ :tags: bug, sql
+ :tickets: 2261, 2319
+
+ further tweak to the fix from,
+ so that generative methods work a bit better
+ off of cloned (this is almost a non-use case though).
+ In particular this allows with_only_columns()
+ to behave more consistently. Added additional
+ documentation to with_only_columns() to clarify
+ expected behavior, which changed as a result
+ of.
+
+ .. change::
+ :tags: engine, bug
+ :tickets: 2317
+
+ Fixed bug whereby transaction.rollback()
+ would throw an error on an invalidated
+ connection if the transaction were a
+ two-phase or savepoint transaction.
+ For plain transactions, rollback() is a no-op
+ if the connection is invalidated, so while
+ it wasn't 100% clear if it should be a no-op,
+ at least now the interface is consistent.
+
+ .. change::
+ :tags: feature, schema
+ :tickets:
+
+ Added new support for remote "schemas":
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ MetaData() accepts "schema" and "quote_schema"
+ arguments, which will be applied to the same-named
+ arguments of a Table
+ or Sequence which leaves these at their default
+ of ``None``.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Sequence accepts "quote_schema" argument
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ tometadata() for Table will use the "schema"
+ of the incoming MetaData for the new Table
+ if the schema argument is explicitly "None"
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Added CreateSchema and DropSchema DDL
+ constructs - these accept just the string
+ name of a schema and a "quote" flag.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ When using default "schema" with MetaData,
+ ForeignKey will also assume the "default" schema
+ when locating remote table. This allows the "schema"
+ argument on MetaData to be applied to any
+ set of Table objects that otherwise don't have
+ a "schema".
+
+ .. change::
+ :tags: schema
+ :tickets: 1679
+
+ a "has_schema" method has been implemented
+ on dialect, but only works on Postgresql so far.
+ Courtesy Manlio Perillo.
+
+ .. change::
+ :tags: feature, schema
+ :tickets: 1410
+
+ The "extend_existing" flag on Table
+ now allows for the reflection process to take
+ effect for a Table object that's already been
+ defined; when autoload=True and extend_existing=True
+ are both set, the full set of columns will be
+ reflected from the Table which will then
+ *overwrite* those columns already present,
+ rather than no activity occurring. Columns that
+ are present directly in the autoload run
+ will be used as always, however.
+
+ .. change::
+ :tags: bug, schema
+ :tickets:
+
+ Fixed bug whereby TypeDecorator would
+ return a stale value for _type_affinity, when
+ using a TypeDecorator that "switches" types,
+ like the CHAR/UUID type.
+
+ .. change::
+ :tags: bug, schema
+ :tickets:
+
+ Fixed bug whereby "order_by='foreign_key'"
+ option to Inspector.get_table_names
+ wasn't implementing the sort properly, replaced
+ with the existing sort algorithm
+
+ .. change::
+ :tags: bug, schema
+ :tickets: 2305
+
+ the "name" of a column-level CHECK constraint,
+ if present, is now rendered in the CREATE TABLE
+ statement using "CONSTRAINT <name> CHECK <expression>".
+
+ .. change::
+ :tags: pyodbc, bug
+ :tickets: 2318
+
+ pyodbc-based dialects now parse the
+ pyodbc accurately as far as observed
+ pyodbc strings, including such gems
+ as "py3-3.0.1-beta4"
+
+ .. change::
+ :tags: postgresql, bug
+ :tickets: 2311
+
+ Postgresql dialect memoizes that an ENUM of a
+ particular name was processed
+ during a create/drop sequence. This allows
+ a create/drop sequence to work without any
+ calls to "checkfirst", and also means with
+ "checkfirst" turned on it only needs to
+ check for the ENUM once.
+
+ .. change::
+ :tags: postgresql, feature
+ :tickets:
+
+ Added create_type constructor argument
+ to pg.ENUM. When False, no CREATE/DROP or
+ checking for the type will be performed as part
+ of a table create/drop event; only the
+ create()/drop)() methods called directly
+ will do this. Helps with Alembic "offline"
+ scripts.
+
+ .. change::
+ :tags: mssql, feature
+ :tickets: 822
+
+ lifted the restriction on SAVEPOINT
+ for SQL Server. All tests pass using it,
+ it's not known if there are deeper issues
+ however.
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2336
+
+ repaired the with_hint() feature which
+ wasn't implemented correctly on MSSQL -
+ usually used for the "WITH (NOLOCK)" hint
+ (which you shouldn't be using anyway !
+ use snapshot isolation instead :) )
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2318
+
+ use new pyodbc version detection for
+ _need_decimal_fix option.
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2343
+
+ don't cast "table name" as NVARCHAR
+ on SQL Server 2000. Still mostly in the dark
+ what incantations are needed to make PyODBC
+ work fully with FreeTDS 0.91 here, however.
+
+ .. change::
+ :tags: mssql, bug
+ :tickets: 2269
+
+ Decode incoming values when retrieving
+ list of index names and the names of columns
+ within those indexes.
+
+ .. change::
+ :tags: bug, mysql
+ :tickets:
+
+ Unicode adjustments allow latest pymysql
+ (post 0.4) to pass 100% on Python 2.
+
+ .. change::
+ :tags: ext, feature
+ :tickets:
+
+ Added an example to the hybrid docs
+ of a "transformer" - a hybrid that returns a
+ query-transforming callable in combination
+ with a custom comparator. Uses a new method
+ on Query called with_transformation(). The use
+ case here is fairly experimental, but only
+ adds one line of code to Query.
+
+ .. change::
+ :tags: ext, bug
+ :tickets:
+
+ the @compiles decorator raises an
+ informative error message when no "default"
+ compilation handler is present, rather
+ than KeyError.
+
+ .. change::
+ :tags: examples, bug
+ :tickets:
+
+ Fixed bug in history_meta.py example where
+ the "unique" flag was not removed from a
+ single-table-inheritance subclass which
+ generates columns to put up onto the base.
+
+.. changelog::
+ :version: 0.7.3
+ :released: Sun Oct 16 2011
+
+ .. change::
+ :tags: general
+ :tickets: 2279
+
+ Adjusted the "importlater" mechanism, which is
+ used internally to resolve import cycles,
+ such that the usage of __import__ is completed
+ when the import of sqlalchemy or sqlalchemy.orm
+ is done, thereby avoiding any usage of __import__
+ after the application starts new threads,
+ fixes. Also in 0.6.9.
+
+ .. change::
+ :tags: orm
+ :tickets: 2298
+
+ Improved query.join() such that the "left" side
+ can more flexibly be a non-ORM selectable,
+ such as a subquery. A selectable placed
+ in select_from() will now be used as the left
+ side, favored over implicit usage
+ of a mapped entity.
+ If the join still fails based on lack of
+ foreign keys, the error message includes
+ this detail. Thanks to brianrhude
+ on IRC for the test case.
+
+ .. change::
+ :tags: orm
+ :tickets: 2241
+
+ Added after_soft_rollback() Session event. This
+ event fires unconditionally whenever rollback()
+ is called, regardless of if an actual DBAPI
+ level rollback occurred. This event
+ is specifically designed to allow operations
+ with the Session to proceed after a rollback
+ when the Session.is_active is True.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added "adapt_on_names" boolean flag to orm.aliased()
+ construct. Allows an aliased() construct
+ to link the ORM entity to a selectable that contains
+ aggregates or other derived forms of a particular
+ attribute, provided the name is the same as that
+ of the entity mapped column.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added new flag expire_on_flush=False to column_property(),
+ marks those properties that would otherwise be considered
+ to be "readonly", i.e. derived from SQL expressions,
+ to retain their value after a flush has occurred, including
+ if the parent object itself was involved in an update.
+
+ .. change::
+ :tags: orm
+ :tickets: 2237
+
+ Enhanced the instrumentation in the ORM to support
+ Py3K's new argument style of "required kw arguments",
+ i.e. fn(a, b, *, c, d), fn(a, b, *args, c, d).
+ Argument signatures of mapped object's __init__
+ method will be preserved, including required kw rules.
+
+ .. change::
+ :tags: orm
+ :tickets: 2282
+
+ Fixed bug in unit of work whereby detection of
+ "cycles" among classes in highly interlinked patterns
+ would not produce a deterministic
+ result; thereby sometimes missing some nodes that
+ should be considered cycles and causing further
+ issues down the road. Note this bug is in 0.6
+ also; not backported at the moment.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Fixed a variety of synonym()-related regressions
+ from 0.6:
+ - making a synonym against a synonym now works.
+ - synonyms made against a relationship() can
+ be passed to query.join(), options sent
+ to query.options(), passed by name
+ to query.with_parent().
+
+ .. change::
+ :tags: orm
+ :tickets: 2287
+
+ Fixed bug whereby mapper.order_by attribute would
+ be ignored in the "inner" query within a
+ subquery eager load. .
+ Also in 0.6.9.
+
+ .. change::
+ :tags: orm
+ :tickets: 2267
+
+ Identity map .discard() uses dict.pop(,None)
+ internally instead of "del" to avoid KeyError/warning
+ during a non-determinate gc teardown
+
+ .. change::
+ :tags: orm
+ :tickets: 2253
+
+ Fixed regression in new composite rewrite where
+ deferred=True option failed due to missing
+ import
+
+ .. change::
+ :tags: orm
+ :tickets: 2248
+
+ Reinstated "comparator_factory" argument to
+ composite(), removed when 0.7 was released.
+
+ .. change::
+ :tags: orm
+ :tickets: 2247
+
+ Fixed bug in query.join() which would occur
+ in a complex multiple-overlapping path scenario,
+ where the same table could be joined to
+ twice. Thanks *much* to Dave Vitek
+ for the excellent fix here.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query will convert an OFFSET of zero when
+ slicing into None, so that needless OFFSET
+ clauses are not invoked.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Repaired edge case where mapper would fail
+ to fully update internal state when a relationship
+ on a new mapper would establish a backref on the
+ first mapper.
+
+ .. change::
+ :tags: orm
+ :tickets: 2260
+
+ Fixed bug whereby if __eq__() was
+ redefined, a relationship many-to-one lazyload
+ would hit the __eq__() and fail.
+ Does not apply to 0.6.9.
+
+ .. change::
+ :tags: orm
+ :tickets: 2196
+
+ Calling class_mapper() and passing in an object
+ that is not a "type" (i.e. a class that could
+ potentially be mapped) now raises an informative
+ ArgumentError, rather than UnmappedClassError.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ New event hook, MapperEvents.after_configured().
+ Called after a configure() step has completed and
+ mappers were in fact affected. Theoretically this
+ event is called once per application, unless new mappings
+ are constructed after existing ones have been used
+ already.
+
+ .. change::
+ :tags: orm
+ :tickets: 2281
+
+ When an open Session is garbage collected, the objects
+ within it which remain are considered detached again
+ when they are add()-ed to a new Session.
+ This is accomplished by an extra check that the previous
+ "session_key" doesn't actually exist among the pool
+ of Sessions.
+
+ .. change::
+ :tags: orm
+ :tickets: 2239
+
+ New declarative features:
+ - __declare_last__() method, establishes an event
+ listener for the class method that will be called
+ when mappers are completed with the final "configure"
+ step.
+ - __abstract__ flag. The class will not be mapped
+ at all when this flag is present on the class.
+ - New helper classes ConcreteBase, AbstractConcreteBase.
+ Allow concrete mappings using declarative which automatically
+ set up the "polymorphic_union" when the "configure"
+ mapper step is invoked.
+ - The mapper itself has semi-private methods that allow
+ the "with_polymorphic" selectable to be assigned
+ to the mapper after it has already been configured.
+
+ .. change::
+ :tags: orm
+ :tickets: 2283
+
+ Declarative will warn when a subclass' base uses
+ @declared_attr for a regular column - this attribute
+ does not propagate to subclasses.
+
+ .. change::
+ :tags: orm
+ :tickets: 2280
+
+ The integer "id" used to link a mapped instance with
+ its owning Session is now generated by a sequence
+ generation function rather than id(Session), to
+ eliminate the possibility of recycled id() values
+ causing an incorrect result, no need to check that
+ object actually in the session.
+
+ .. change::
+ :tags: orm
+ :tickets: 2257
+
+ Behavioral improvement: empty
+ conjunctions such as and_() and or_() will be
+ flattened in the context of an enclosing conjunction,
+ i.e. and_(x, or_()) will produce 'X' and not 'X AND
+ ()'..
+
+ .. change::
+ :tags: orm
+ :tickets: 2261
+
+ Fixed bug regarding calculation of "from" list
+ for a select() element. The "from" calc is now
+ delayed, so that if the construct uses a Column
+ object that is not yet attached to a Table,
+ but is later associated with a Table, it generates
+ SQL using the table as a FROM. This change
+ impacted fairly deeply the mechanics of how
+ the FROM list as well as the "correlates" collection
+ is calculated, as some "clause adaption" schemes
+ (these are used very heavily in the ORM)
+ were relying upon the fact that the "froms"
+ collection would typically be cached before the
+ adaption completed. The rework allows it
+ such that the "froms" collection can be cleared
+ and re-generated at any time.
+
+ .. change::
+ :tags: orm
+ :tickets: 2270
+
+ Fixed bug whereby with_only_columns() method of
+ Select would fail if a selectable were passed.. Also in 0.6.9.
+
+ .. change::
+ :tags: schema
+ :tickets: 2284
+
+ Modified Column.copy() to use _constructor(),
+ which defaults to self.__class__, in order to
+ create the new object. This allows easier support
+ of subclassing Column.
+
+ .. change::
+ :tags: schema
+ :tickets: 2223
+
+ Added a slightly nicer __repr__() to SchemaItem
+ classes. Note the repr here can't fully support
+ the "repr is the constructor" idea since schema
+ items can be very deeply nested/cyclical, have
+ late initialization of some things, etc.
+
+ .. change::
+ :tags: engine
+ :tickets: 2254
+
+ The recreate() method in all pool classes uses
+ self.__class__ to get at the type of pool
+ to produce, in the case of subclassing. Note
+ there's no usual need to subclass pools.
+
+ .. change::
+ :tags: engine
+ :tickets: 2243
+
+ Improvement to multi-param statement logging,
+ long lists of bound parameter sets will be
+ compressed with an informative indicator
+ of the compression taking place. Exception
+ messages use the same improved formatting.
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ Added optional "sa_pool_key" argument to
+ pool.manage(dbapi).connect() so that serialization
+ of args is not necessary.
+
+ .. change::
+ :tags: engine
+ :tickets: 2286
+
+ The entry point resolution supported by
+ create_engine() now supports resolution of
+ individual DBAPI drivers on top of a built-in
+ or entry point-resolved dialect, using the
+ standard '+' notation - it's converted to
+ a '.' before being resolved as an entry
+ point.
+
+ .. change::
+ :tags: engine
+ :tickets: 2299
+
+ Added an exception catch + warning for the
+ "return unicode detection" step within connect,
+ allows databases that crash on NVARCHAR to
+ continue initializing, assuming no NVARCHAR
+ type implemented.
+
+ .. change::
+ :tags: types
+ :tickets: 2258
+
+ Extra keyword arguments to the base Float
+ type beyond "precision" and "asdecimal" are ignored;
+ added a deprecation warning here and additional
+ docs, related to
+
+ .. change::
+ :tags: sqlite
+ :tickets:
+
+ Ensured that the same ValueError is raised for
+ illegal date/time/datetime string parsed from
+ the database regardless of whether C
+ extensions are in use or not.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2290
+
+ Added "postgresql_using" argument to Index(), produces
+ USING clause to specify index implementation for
+ PG. . Thanks to Ryan P. Kelly for
+ the patch.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1839
+
+ Added client_encoding parameter to create_engine()
+ when the postgresql+psycopg2 dialect is used;
+ calls the psycopg2 set_client_encoding() method
+ with the value upon connect.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2291, 2141
+
+ Fixed bug related to whereby the
+ same modified index behavior in PG 9 affected
+ primary key reflection on a renamed column.. Also in 0.6.9.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2256
+
+ Reflection functions for Table, Sequence no longer
+ case insensitive. Names can be differ only in case
+ and will be correctly distinguished.
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ Use an atomic counter as the "random number"
+ source for server side cursor names;
+ conflicts have been reported in rare cases.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2249
+
+ Narrowed the assumption made when reflecting
+ a foreign-key referenced table with schema in
+ the current search path; an explicit schema will
+ be applied to the referenced table only if
+ it actually matches that of the referencing table,
+ which also has an explicit schema. Previously
+ it was assumed that "current" schema was synonymous
+ with the full search_path.
+
+ .. change::
+ :tags: mysql
+ :tickets: 2225
+
+ a CREATE TABLE will put the COLLATE option
+ after CHARSET, which appears to be part of
+ MySQL's arbitrary rules regarding if it will actually
+ work or not. Also in 0.6.9.
+
+ .. change::
+ :tags: mysql
+ :tickets: 2293
+
+ Added mysql_length parameter to Index construct,
+ specifies "length" for indexes.
+
+ .. change::
+ :tags: mssql
+ :tickets: 2273
+
+ Changes to attempt support of FreeTDS 0.91 with
+ Pyodbc. This includes that string binds are sent as
+ Python unicode objects when FreeTDS 0.91 is detected,
+ and a CAST(? AS NVARCHAR) is used when we detect
+ for a table. However, I'd continue
+ to characterize Pyodbc + FreeTDS 0.91 behavior as
+ pretty crappy, there are still many queries such
+ as used in reflection which cause a core dump on
+ Linux, and it is not really usable at all
+ on OSX, MemoryErrors abound and just plain broken
+ unicode support.
+
+ .. change::
+ :tags: mssql
+ :tickets: 2277
+
+ The behavior of =/!= when comparing a scalar select
+ to a value will no longer produce IN/NOT IN as of 0.8;
+ this behavior is a little too heavy handed (use in_() if
+ you want to emit IN) and now emits a deprecation warning.
+ To get the 0.8 behavior immediately and remove the warning,
+ a compiler recipe is given at
+ http://www.sqlalchemy.org/docs/07/dialects/mssql.html#scalar-select-comparisons
+ to override the behavior of visit_binary().
+
+ .. change::
+ :tags: mssql
+ :tickets: 2222
+
+ "0" is accepted as an argument for limit() which
+ will produce "TOP 0".
+
+ .. change::
+ :tags: oracle
+ :tickets: 2272
+
+ Fixed ReturningResultProxy for zxjdbc dialect.. Regression from 0.6.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2252
+
+ The String type now generates VARCHAR2 on Oracle
+ which is recommended as the default VARCHAR.
+ Added an explicit VARCHAR2 and NVARCHAR2 to the Oracle
+ dialect as well. Using NVARCHAR still generates
+ "NVARCHAR2" - there is no "NVARCHAR" on Oracle -
+ this remains a slight breakage of the "uppercase types
+ always give exactly that" policy. VARCHAR still
+ generates "VARCHAR", keeping with the policy. If
+ Oracle were to ever define "VARCHAR" as something
+ different as they claim (IMHO this will never happen),
+ the type would be available.
+
+ .. change::
+ :tags: ext
+ :tickets: 2262
+
+ SQLSoup will not be included in version 0.8
+ of SQLAlchemy; while useful, we would like to
+ keep SQLAlchemy itself focused on one ORM
+ usage paradigm. SQLSoup will hopefully
+ soon be superseded by a third party
+ project.
+
+ .. change::
+ :tags: ext
+ :tickets: 2236
+
+ Added local_attr, remote_attr, attr accessors
+ to AssociationProxy, providing quick access
+ to the proxied attributes at the class
+ level.
+
+ .. change::
+ :tags: ext
+ :tickets: 2275
+
+ Changed the update() method on association proxy
+ dictionary to use a duck typing approach, i.e.
+ checks for "keys", to discern between update({})
+ and update((a, b)). Previously, passing a
+ dictionary that had tuples as keys would be misinterpreted
+ as a sequence.
+
+ .. change::
+ :tags: examples
+ :tickets: 2266
+
+ Adjusted dictlike-polymorphic.py example
+ to apply the CAST such that it works on
+ PG, other databases.
+ Also in 0.6.9.
+
+.. changelog::
+ :version: 0.7.2
+ :released: Sun Jul 31 2011
+
+ .. change::
+ :tags: orm
+ :tickets: 2213
+
+ Feature enhancement: joined and subquery
+ loading will now traverse already-present related
+ objects and collections in search of unpopulated
+ attributes throughout the scope of the eager load
+ being defined, so that the eager loading that is
+ specified via mappings or query options
+ unconditionally takes place for the full depth,
+ populating whatever is not already populated.
+ Previously, this traversal would stop if a related
+ object or collection were already present leading
+ to inconsistent behavior (though would save on
+ loads/cycles for an already-loaded graph). For a
+ subqueryload, this means that the additional
+ SELECT statements emitted by subqueryload will
+ invoke unconditionally, no matter how much of the
+ existing graph is already present (hence the
+ controversy). The previous behavior of "stopping"
+ is still in effect when a query is the result of
+ an attribute-initiated lazyload, as otherwise an
+ "N+1" style of collection iteration can become
+ needlessly expensive when the same related object
+ is encountered repeatedly. There's also an
+ as-yet-not-public generative Query method
+ _with_invoke_all_eagers()
+ which selects old/new behavior
+
+ .. change::
+ :tags: orm
+ :tickets: 2195
+
+ A rework of "replacement traversal" within
+ the ORM as it alters selectables to be against
+ aliases of things (i.e. clause adaption) includes
+ a fix for multiply-nested any()/has() constructs
+ against a joined table structure.
+
+ .. change::
+ :tags: orm
+ :tickets: 2234
+
+ Fixed bug where query.join() + aliased=True
+ from a joined-inh structure to itself on
+ relationship() with join condition on the child
+ table would convert the lead entity into the
+ joined one inappropriately.
+ Also in 0.6.9.
+
+ .. change::
+ :tags: orm
+ :tickets: 2205
+
+ Fixed regression from 0.6 where Session.add()
+ against an object which contained None in a
+ collection would raise an internal exception.
+ Reverted this to 0.6's behavior which is to
+ accept the None but obviously nothing is
+ persisted. Ideally, collections with None
+ present or on append() should at least emit a
+ warning, which is being considered for 0.8.
+
+ .. change::
+ :tags: orm
+ :tickets: 2191
+
+ Load of a deferred() attribute on an object
+ where row can't be located raises
+ ObjectDeletedError instead of failing later
+ on; improved the message in ObjectDeletedError
+ to include other conditions besides a simple
+ "delete".
+
+ .. change::
+ :tags: orm
+ :tickets: 2224
+
+ Fixed regression from 0.6 where a get history
+ operation on some relationship() based attributes
+ would fail when a lazyload would emit; this could
+ trigger within a flush() under certain conditions. Thanks to the user who submitted
+ the great test for this.
+
+ .. change::
+ :tags: orm
+ :tickets: 2228
+
+ Fixed bug apparent only in Python 3 whereby
+ sorting of persistent + pending objects during
+ flush would produce an illegal comparison,
+ if the persistent object primary key
+ is not a single integer.
+ Also in 0.6.9
+
+ .. change::
+ :tags: orm
+ :tickets: 2197
+
+ Fixed bug whereby the source clause
+ used by query.join() would be inconsistent
+ if against a column expression that combined
+ multiple entities together.
+ Also in 0.6.9
+
+ .. change::
+ :tags: orm
+ :tickets: 2215
+
+ Fixed bug whereby if a mapped class
+ redefined __hash__() or __eq__() to something
+ non-standard, which is a supported use case
+ as SQLA should never consult these,
+ the methods would be consulted if the class
+ was part of a "composite" (i.e. non-single-entity)
+ result set.
+ Also in 0.6.9.
+
+ .. change::
+ :tags: orm
+ :tickets: 2240
+
+ Added public attribute ".validators" to
+ Mapper, an immutable dictionary view of
+ all attributes that have been decorated
+ with the @validates decorator. courtesy Stefano Fontanelli
+
+ .. change::
+ :tags: orm
+ :tickets: 2188
+
+ Fixed subtle bug that caused SQL to blow
+ up if: column_property() against subquery +
+ joinedload + LIMIT + order by the column
+ property() occurred. .
+ Also in 0.6.9
+
+ .. change::
+ :tags: orm
+ :tickets: 2207
+
+ The join condition produced by with_parent
+ as well as when using a "dynamic" relationship
+ against a parent will generate unique
+ bindparams, rather than incorrectly repeating
+ the same bindparam. .
+ Also in 0.6.9.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Added the same "columns-only" check to
+ mapper.polymorphic_on as used when
+ receiving user arguments to
+ relationship.order_by, foreign_keys,
+ remote_side, etc.
+
+ .. change::
+ :tags: orm
+ :tickets: 2190
+
+ Fixed bug whereby comparison of column
+ expression to a Query() would not call
+ as_scalar() on the underlying SELECT
+ statement to produce a scalar subquery,
+ in the way that occurs if you called
+ it on Query().subquery().
+
+ .. change::
+ :tags: orm
+ :tickets: 2194
+
+ Fixed declarative bug where a class inheriting
+ from a superclass of the same name would fail
+ due to an unnecessary lookup of the name
+ in the _decl_class_registry.
+
+ .. change::
+ :tags: orm
+ :tickets: 2199
+
+ Repaired the "no statement condition"
+ assertion in Query which would attempt
+ to raise if a generative method were called
+ after from_statement() were called.. Also in 0.6.9.
+
+ .. change::
+ :tags: sql
+ :tickets: 2188
+
+ Fixed two subtle bugs involving column
+ correspondence in a selectable,
+ one with the same labeled subquery repeated, the other
+ when the label has been "grouped" and
+ loses itself. Affects.
+
+ .. change::
+ :tags: schema
+ :tickets: 2187
+
+ New feature: with_variant() method on
+ all types. Produces an instance of Variant(),
+ a special TypeDecorator which will select
+ the usage of a different type based on the
+ dialect in use.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Added an informative error message when
+ ForeignKeyConstraint refers to a column name in
+ the parent that is not found. Also in 0.6.9.
+
+ .. change::
+ :tags: schema
+ :tickets: 2206
+
+ Fixed bug whereby adaptation of old append_ddl_listener()
+ function was passing unexpected **kw through
+ to the Table event. Table gets no kws, the MetaData
+ event in 0.6 would get "tables=somecollection",
+ this behavior is preserved.
+
+ .. change::
+ :tags: schema
+ :tickets:
+
+ Fixed bug where "autoincrement" detection on
+ Table would fail if the type had no "affinity"
+ value, in particular this would occur when using
+ the UUID example on the site that uses TypeEngine
+ as the "impl".
+
+ .. change::
+ :tags: schema
+ :tickets: 2209
+
+ Added an improved repr() to TypeEngine objects
+ that will only display constructor args which
+ are positional or kwargs that deviate
+ from the default.
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ Context manager provided by Connection.begin()
+ will issue rollback() if the commit() fails,
+ not just if an exception occurs.
+
+ .. change::
+ :tags: engine
+ :tickets: 1682
+
+ Use urllib.parse_qsl() in Python 2.6 and above,
+ no deprecation warning about cgi.parse_qsl()
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ Added mixin class sqlalchemy.ext.DontWrapMixin.
+ User-defined exceptions of this type are never
+ wrapped in StatementException when they
+ occur in the context of a statement
+ execution.
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ StatementException wrapping will display the
+ original exception class in the message.
+
+ .. change::
+ :tags: engine
+ :tickets: 2201
+
+ Failures on connect which raise dbapi.Error
+ will forward the error to dialect.is_disconnect()
+ and set the "connection_invalidated" flag if
+ the dialect knows this to be a potentially
+ "retryable" condition. Only Oracle ORA-01033
+ implemented for now.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 2189
+
+ SQLite dialect no longer strips quotes
+ off of reflected default value, allowing
+ a round trip CREATE TABLE to work.
+ This is consistent with other dialects
+ that also maintain the exact form of
+ the default.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2198
+
+ Added new "postgresql_ops" argument to
+ Index, allows specification of PostgreSQL
+ operator classes for indexed columns. Courtesy Filip Zyzniewski.
+
+ .. change::
+ :tags: mysql
+ :tickets: 2186
+
+ Fixed OurSQL dialect to use ansi-neutral
+ quote symbol "'" for XA commands instead
+ of '"'. . Also in 0.6.9.
+
+ .. change::
+ :tags: mssql
+ :tickets:
+
+ Adjusted the pyodbc dialect such that bound
+ values are passed as bytes and not unicode
+ if the "Easysoft" unix drivers are detected.
+ This is the same behavior as occurs with
+ FreeTDS. Easysoft appears to segfault
+ if Python unicodes are passed under
+ certain circumstances.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2200
+
+ Added ORA-00028 to disconnect codes, use
+ cx_oracle _Error.code to get at the code,. Also in 0.6.9.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2201
+
+ Added ORA-01033 to disconnect codes, which
+ can be caught during a connection
+ event.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2220
+
+ repaired the oracle.RAW type which did not
+ generate the correct DDL.
+ Also in 0.6.9.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2212
+
+ added CURRENT to reserved word list. Also in 0.6.9.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Fixed bug in the mutable extension whereby
+ if the same type were used twice in one
+ mapping, the attributes beyond the first
+ would not get instrumented.
+
+ .. change::
+ :tags: oracle
+ :tickets:
+
+ Fixed bug in the mutable extension whereby
+ if None or a non-corresponding type were set,
+ an error would be raised. None is now accepted
+ which assigns None to all attributes,
+ illegal values raise ValueError.
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ Repaired the examples/versioning test runner
+ to not rely upon SQLAlchemy test libs,
+ nosetests must be run from within
+ examples/versioning to get around setup.cfg
+ breaking it.
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ Tweak to examples/versioning to pick the
+ correct foreign key in a multi-level
+ inheritance situation.
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ Fixed the attribute shard example to check
+ for bind param callable correctly in 0.7
+ style.
+
+.. changelog::
+ :version: 0.7.1
+ :released: Sun Jun 05 2011
+
+ .. change::
+ :tags: general
+ :tickets: 2184
+
+ Added a workaround for Python bug 7511 where
+ failure of C extension build does not
+ raise an appropriate exception on Windows 64
+ bit + VC express
+
+ .. change::
+ :tags: orm
+ :tickets: 1912
+
+ "delete-orphan" cascade is now allowed on
+ self-referential relationships - this since
+ SQLA 0.7 no longer enforces "parent with no
+ child" at the ORM level; this check is left
+ up to foreign key nullability.
+ Related to
+
+ .. change::
+ :tags: orm
+ :tickets: 2180
+
+ Repaired new "mutable" extension to propagate
+ events to subclasses correctly; don't
+ create multiple event listeners for
+ subclasses either.
+
+ .. change::
+ :tags: orm
+ :tickets: 2170
+
+ Modify the text of the message which occurs
+ when the "identity" key isn't detected on
+ flush, to include the common cause that
+ the Column isn't set up to detect
+ auto-increment correctly;.
+ Also in 0.6.8.
+
+ .. change::
+ :tags: orm
+ :tickets: 2182
+
+ Fixed bug where transaction-level "deleted"
+ collection wouldn't be cleared of expunged
+ states, raising an error if they later
+ became transient.
+ Also in 0.6.8.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Fixed bug whereby metadata.reflect(bind)
+ would close a Connection passed as a
+ bind argument. Regression from 0.6.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Streamlined the process by which a Select
+ determines what's in it's '.c' collection.
+ Behaves identically, except that a
+ raw ClauseList() passed to select([])
+ (which is not a documented case anyway) will
+ now be expanded into its individual column
+ elements instead of being ignored.
+
+ .. change::
+ :tags: engine
+ :tickets:
+
+ Deprecate schema/SQL-oriented methods on
+ Connection/Engine that were never well known
+ and are redundant: reflecttable(), create(),
+ drop(), text(), engine.func
+
+ .. change::
+ :tags: engine
+ :tickets: 2178
+
+ Adjusted the __contains__() method of
+ a RowProxy result row such that no exception
+ throw is generated internally;
+ NoSuchColumnError() also will generate its
+ message regardless of whether or not the column
+ construct can be coerced to a string.. Also in 0.6.8.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 2173
+
+ Accept None from cursor.fetchone() when
+ "PRAGMA read_uncommitted" is called to determine
+ current isolation mode at connect time and
+ default to SERIALIZABLE; this to support SQLite
+ versions pre-3.3.0 that did not have this
+ feature.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2175
+
+ Some unit test fixes regarding numeric arrays,
+ MATCH operator. A potential floating-point
+ inaccuracy issue was fixed, and certain tests
+ of the MATCH operator only execute within an
+ EN-oriented locale for now. .
+ Also in 0.6.8.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ Unit tests pass 100% on MySQL installed
+ on windows.
+
+ .. change::
+ :tags: mysql
+ :tickets: 2181
+
+ Removed the "adjust casing" step that would
+ fail when reflecting a table on MySQL
+ on windows with a mixed case name. After some
+ experimenting with a windows MySQL server, it's
+ been determined that this step wasn't really
+ helping the situation much; MySQL does not return
+ FK names with proper casing on non-windows
+ platforms either, and removing the step at
+ least allows the reflection to act more like
+ it does on other OSes. A warning here
+ has been considered but its difficult to
+ determine under what conditions such a warning
+ can be raised, so punted on that for now -
+ added some docs instead.
+
+ .. change::
+ :tags: mysql
+ :tickets:
+
+ supports_sane_rowcount will be set to False
+ if using MySQLdb and the DBAPI doesn't provide
+ the constants.CLIENT module.
+
+.. changelog::
+ :version: 0.7.0
+ :released: Fri May 20 2011
+
+ .. change::
+ :tags:
+ :tickets:
+
+ This section documents those changes from 0.7b4
+ to 0.7.0. For an overview of what's new in
+ SQLAlchemy 0.7, see
+ http://www.sqlalchemy.org/trac/wiki/07Migration
+
+ .. change::
+ :tags: orm
+ :tickets: 2069
+
+ Fixed regression introduced in 0.7b4 (!) whereby
+ query.options(someoption("nonexistent name")) would
+ fail to raise an error. Also added additional
+ error catching for cases where the option would
+ try to build off a column-based element, further
+ fixed up some of the error messages tailored
+ in
+
+ .. change::
+ :tags: orm
+ :tickets: 2162
+
+ query.count() emits "count(*)" instead of
+ "count(1)".
+
+ .. change::
+ :tags: orm
+ :tickets: 2155
+
+ Fine tuning of Query clause adaptation when
+ from_self(), union(), or other "select from
+ myself" operation, such that plain SQL expression
+ elements added to filter(), order_by() etc.
+ which are present in the nested "from myself"
+ query *will* be adapted in the same way an ORM
+ expression element will, since these
+ elements are otherwise not easily accessible.
+
+ .. change::
+ :tags: orm
+ :tickets: 2149
+
+ Fixed bug where determination of "self referential"
+ relationship would fail with no workaround
+ for joined-inh subclass related to itself,
+ or joined-inh subclass related to a subclass
+ of that with no cols in the sub-sub class
+ in the join condition.
+ Also in 0.6.8.
+
+ .. change::
+ :tags: orm
+ :tickets: 2153
+
+ mapper() will ignore non-configured foreign keys
+ to unrelated tables when determining inherit
+ condition between parent and child class,
+ but will raise as usual for unresolved
+ columns and table names regarding the inherited
+ table. This is an enhanced generalization of
+ behavior that was already applied to declarative
+ previously. 0.6.8 has a more
+ conservative version of this which doesn't
+ fundamentally alter how join conditions
+ are determined.
+
+ .. change::
+ :tags: orm
+ :tickets: 2144
+
+ It is an error to call query.get() when the
+ given entity is not a single, full class
+ entity or mapper (i.e. a column). This is
+ a deprecation warning in 0.6.8.
+
+ .. change::
+ :tags: orm
+ :tickets: 2148
+
+ Fixed a potential KeyError which under some
+ circumstances could occur with the identity
+ map, part of
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ added Query.with_session() method, switches
+ Query to use a different session.
+
+ .. change::
+ :tags: orm
+ :tickets: 2131
+
+ horizontal shard query should use execution
+ options per connection as per
+
+ .. change::
+ :tags: orm
+ :tickets: 2151
+
+ a non_primary mapper will inherit the _identity_class
+ of the primary mapper. This so that a non_primary
+ established against a class that's normally in an
+ inheritance mapping will produce results that are
+ identity-map compatible with that of the primary
+ mapper (also in 0.6.8)
+
+ .. change::
+ :tags: orm
+ :tickets: 2163
+
+ Fixed the error message emitted for "can't
+ execute syncrule for destination column 'q';
+ mapper 'X' does not map this column" to
+ reference the correct mapper. .
+ Also in 0.6.8.
+
+ .. change::
+ :tags: orm
+ :tickets: 1502
+
+ polymorphic_union() gets a "cast_nulls" option,
+ disables the usage of CAST when it renders
+ the labeled NULL columns.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ polymorphic_union() renders the columns in their
+ original table order, as according to the first
+ table/selectable in the list of polymorphic
+ unions in which they appear. (which is itself
+ an unordered mapping unless you pass an OrderedDict).
+
+ .. change::
+ :tags: orm
+ :tickets: 2171
+
+ Fixed bug whereby mapper mapped to an anonymous
+ alias would fail if logging were used, due to
+ unescaped % sign in the alias name.
+ Also in 0.6.8.
+
+ .. change::
+ :tags: sql
+ :tickets: 2167
+
+ Fixed bug whereby nesting a label of a select()
+ with another label in it would produce incorrect
+ exported columns. Among other things this would
+ break an ORM column_property() mapping against
+ another column_property(). .
+ Also in 0.6.8
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Changed the handling in determination of join
+ conditions such that foreign key errors are
+ only considered between the two given tables.
+ That is, t1.join(t2) will report FK errors
+ that involve 't1' or 't2', but anything
+ involving 't3' will be skipped. This affects
+ join(), as well as ORM relationship and
+ inherit condition logic.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Some improvements to error handling inside
+ of the execute procedure to ensure auto-close
+ connections are really closed when very
+ unusual DBAPI errors occur.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ metadata.reflect() and reflection.Inspector()
+ had some reliance on GC to close connections
+ which were internally procured, fixed this.
+
+ .. change::
+ :tags: sql
+ :tickets: 2140
+
+ Added explicit check for when Column .name
+ is assigned as blank string
+
+ .. change::
+ :tags: sql
+ :tickets: 2147
+
+ Fixed bug whereby if FetchedValue was passed
+ to column server_onupdate, it would not
+ have its parent "column" assigned, added
+ test coverage for all column default assignment
+ patterns. also in 0.6.8
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ Fixed the psycopg2_version parsing in the
+ psycopg2 dialect.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2141
+
+ Fixed bug affecting PG 9 whereby index reflection
+ would fail if against a column whose name
+ had changed. . Also in 0.6.8.
+
+ .. change::
+ :tags: mssql
+ :tickets: 2169
+
+ Fixed bug in MSSQL dialect whereby the aliasing
+ applied to a schema-qualified table would leak
+ into enclosing select statements.
+ Also in 0.6.8.
+
+ .. change::
+ :tags: documentation
+ :tickets: 2152
+
+ Removed the usage of the "collections.MutableMapping"
+ abc from the ext.mutable docs as it was being used
+ incorrectly and makes the example more difficult
+ to understand in any case.
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ removed the ancient "polymorphic association"
+ examples and replaced with an updated set of
+ examples that use declarative mixins,
+ "generic_associations". Each presents an alternative
+ table layout.
+
+ .. change::
+ :tags: ext
+ :tickets: 2143
+
+ Fixed bugs in sqlalchemy.ext.mutable extension where
+ `None` was not appropriately handled, replacement
+ events were not appropriately handled.
+
+.. changelog::
+ :version: 0.7.0b4
+ :released: Sun Apr 17 2011
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ Changes to the format of CHANGES, this file.
+ The format changes have been applied to
+ the 0.7 releases.
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ The "-declarative" changes will now be listed
+ directly under the "-orm" section, as these
+ are closely related.
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ The 0.5 series changes have been moved to
+ the file CHANGES_PRE_06 which replaces
+ CHANGES_PRE_05.
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ The changelog for 0.6.7 and subsequent within
+ the 0.6 series is now listed only in the
+ CHANGES file within the 0.6 branch.
+ In the 0.7 CHANGES file (i.e. this file), all the
+ 0.6 changes are listed inline within the 0.7
+ section in which they were also applied
+ (since all 0.6 changes are in 0.7 as well).
+ Changes that apply to an 0.6 version here
+ are noted as are if any differences in
+ implementation/behavior are present.
+
+ .. change::
+ :tags: orm
+ :tickets: 2122
+
+ Some fixes to "evaulate" and "fetch" evaluation
+ when query.update(), query.delete() are called.
+ The retrieval of records is done after autoflush
+ in all cases, and before update/delete is
+ emitted, guarding against unflushed data present
+ as well as expired objects failing during
+ the evaluation.
+
+ .. change::
+ :tags: orm
+ :tickets: 2063
+
+ Reworded the exception raised when a flush
+ is attempted of a subclass that is not polymorphic
+ against the supertype.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Still more wording adjustments when a query option
+ can't find the target entity. Explain that the
+ path must be from one of the root entities.
+
+ .. change::
+ :tags: orm
+ :tickets: 2123
+
+ Some fixes to the state handling regarding
+ backrefs, typically when autoflush=False, where
+ the back-referenced collection wouldn't
+ properly handle add/removes with no net
+ change. Thanks to Richard Murri for the
+ test case + patch.
+ (also in 0.6.7).
+
+ .. change::
+ :tags: orm
+ :tickets: 2127
+
+ Added checks inside the UOW to detect the unusual
+ condition of being asked to UPDATE or DELETE
+ on a primary key value that contains NULL
+ in it.
+
+ .. change::
+ :tags: orm
+ :tickets: 2127
+
+ Some refinements to attribute history. More
+ changes are pending possibly in 0.8, but
+ for now history has been modified such that
+ scalar history doesn't have a "side effect"
+ of populating None for a non-present value.
+ This allows a slightly better ability to
+ distinguish between a None set and no actual
+ change, affects as well.
+
+ .. change::
+ :tags: orm
+ :tickets: 2130
+
+ a "having" clause would be copied from the
+ inside to the outside query if from_self()
+ were used; in particular this would break
+ an 0.7 style count() query.
+ (also in 0.6.7)
+
+ .. change::
+ :tags: orm
+ :tickets: 2131
+
+ the Query.execution_options() method now passes
+ those options to the Connection rather than
+ the SELECT statement, so that all available
+ options including isolation level and
+ compiled cache may be used.
+
+ .. change::
+ :tags: sql
+ :tickets: 2131
+
+ The "compiled_cache" execution option now raises
+ an error when passed to a SELECT statement
+ rather than a Connection. Previously it was
+ being ignored entirely. We may look into
+ having this option work on a per-statement
+ level at some point.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Restored the "catchall" constructor on the base
+ TypeEngine class, with a deprecation warning.
+ This so that code which does something like
+ Integer(11) still succeeds.
+
+ .. change::
+ :tags: sql
+ :tickets: 2104
+
+ Fixed regression whereby MetaData() coming
+ back from unpickling did not keep track of
+ new things it keeps track of now, i.e.
+ collection of Sequence objects, list
+ of schema names.
+
+ .. change::
+ :tags: sql
+ :tickets: 2116
+
+ The limit/offset keywords to select() as well
+ as the value passed to select.limit()/offset()
+ will be coerced to integer.
+ (also in 0.6.7)
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ fixed bug where "from" clause gathering from an
+ over() clause would be an itertools.chain() and
+ not a list, causing "can only concatenate list"
+ TypeError when combined with other clauses.
+
+ .. change::
+ :tags: sql
+ :tickets: 2134
+
+ Fixed incorrect usage of "," in over() clause
+ being placed between the "partition" and "order by"
+ clauses.
+
+ .. change::
+ :tags: sql
+ :tickets: 2105
+
+ Before/after attach events for PrimaryKeyConstraint
+ now function, tests added for before/after events
+ on all constraint types.
+
+ .. change::
+ :tags: sql
+ :tickets: 2117
+
+ Added explicit true()/false() constructs to expression
+ lib - coercion rules will intercept "False"/"True"
+ into these constructs. In 0.6, the constructs were
+ typically converted straight to string, which was
+ no longer accepted in 0.7.
+
+ .. change::
+ :tags: engine
+ :tickets: 2129
+
+ The C extension is now enabled by default on CPython
+ 2.x with a fallback to pure python if it fails to
+ compile.
+
+ .. change::
+ :tags: schema
+ :tickets: 2109
+
+ The 'useexisting' flag on Table has been superceded
+ by a new pair of flags 'keep_existing' and
+ 'extend_existing'. 'extend_existing' is equivalent
+ to 'useexisting' - the existing Table is returned,
+ and additional constructor elements are added.
+ With 'keep_existing', the existing Table is returned,
+ but additional constructor elements are not added -
+ these elements are only applied when the Table
+ is newly created.
+
+ .. change::
+ :tags: types
+ :tickets: 2081
+
+ REAL has been added to the core types. Supported
+ by Postgresql, SQL Server, MySQL, SQLite. Note
+ that the SQL Server and MySQL versions, which
+ add extra arguments, are also still available
+ from those dialects.
+
+ .. change::
+ :tags: types
+ :tickets: 2106
+
+ Added @event.listens_for() decorator, given
+ target + event name, applies the decorated
+ function as a listener.
+
+ .. change::
+ :tags: pool
+ :tickets: 2103
+
+ AssertionPool now stores the traceback indicating
+ where the currently checked out connection was
+ acquired; this traceback is reported within
+ the assertion raised upon a second concurrent
+ checkout; courtesy Gunnlaugur Briem
+
+ .. change::
+ :tags: pool
+ :tickets:
+
+ The "pool.manage" feature doesn't use pickle
+ anymore to hash the arguments for each pool.
+
+ .. change::
+ :tags: sqlite
+ :tickets: 2115
+
+ Fixed bug where reflection of foreign key
+ created as "REFERENCES <tablename>" without
+ col name would fail.
+ (also in 0.6.7)
+
+ .. change::
+ :tags: postgresql
+ :tickets:
+
+ Psycopg2 for Python 3 is now supported.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2132
+
+ Fixed support for precision numerics when using
+ pg8000.
+
+ .. change::
+ :tags: oracle
+ :tickets: 2100
+
+ Using column names that would require quotes
+ for the column itself or for a name-generated
+ bind parameter, such as names with special
+ characters, underscores, non-ascii characters,
+ now properly translate bind parameter keys when
+ talking to cx_oracle. (Also
+ in 0.6.7)
+
+ .. change::
+ :tags: oracle
+ :tickets: 2116
+
+ Oracle dialect adds use_binds_for_limits=False
+ create_engine() flag, will render the LIMIT/OFFSET
+ values inline instead of as binds, reported to
+ modify the execution plan used by Oracle. (Also in 0.6.7)
+
+ .. change::
+ :tags: documentation
+ :tickets: 2029
+
+ Documented SQLite DATE/TIME/DATETIME types. (also in 0.6.7)
+
+ .. change::
+ :tags: documentation
+ :tickets: 2118
+
+ Fixed mutable extension docs to show the
+ correct type-association methods.
+
+.. changelog::
+ :version: 0.7.0b3
+ :released: Sun Mar 20 2011
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ Lots of fixes to unit tests when run under Pypy
+ (courtesy Alex Gaynor).
+
+ .. change::
+ :tags: orm
+ :tickets: 2093
+
+ Changed the underlying approach to query.count().
+ query.count() is now in all cases exactly:
+
+ query.
+ from_self(func.count(literal_column('1'))).
+ scalar()
+
+ That is, "select count(1) from (<full query>)".
+ This produces a subquery in all cases, but
+ vastly simplifies all the guessing count()
+ tried to do previously, which would still
+ fail in many scenarios particularly when
+ joined table inheritance and other joins
+ were involved. If the subquery produced
+ for an otherwise very simple count is really
+ an issue, use query(func.count()) as an
+ optimization.
+
+ .. change::
+ :tags: orm
+ :tickets: 2087
+
+ some changes to the identity map regarding
+ rare weakref callbacks during iterations.
+ The mutex has been removed as it apparently
+ can cause a reentrant (i.e. in one thread) deadlock,
+ perhaps when gc collects objects at the point of
+ iteration in order to gain more memory. It is hoped
+ that "dictionary changed during iteration" will
+ be exceedingly rare as iteration methods internally
+ acquire the full list of objects in a single values()
+ call. Note 0.6.7 has a more conservative fix here
+ which still keeps the mutex in place.
+
+ .. change::
+ :tags: orm
+ :tickets: 2082
+
+ A tweak to the unit of work causes it to order
+ the flush along relationship() dependencies even if
+ the given objects don't have any inter-attribute
+ references in memory, which was the behavior in
+ 0.5 and earlier, so a flush of Parent/Child with
+ only foreign key/primary key set will succeed.
+ This while still maintaining 0.6 and above's not
+ generating a ton of useless internal dependency
+ structures within the flush that don't correspond
+ to state actually within the current flush.
+
+ .. change::
+ :tags: orm
+ :tickets: 2069
+
+ Improvements to the error messages emitted when
+ querying against column-only entities in conjunction
+ with (typically incorrectly) using loader options,
+ where the parent entity is not fully present.
+
+ .. change::
+ :tags: orm
+ :tickets: 2098
+
+ Fixed bug in query.options() whereby a path
+ applied to a lazyload using string keys could
+ overlap a same named attribute on the wrong
+ entity. Note 0.6.7 has a more conservative fix
+ to this.
+
+ .. change::
+ :tags: declarative
+ :tickets: 2091
+
+ Arguments in __mapper_args__ that aren't "hashable"
+ aren't mistaken for always-hashable, possibly-column
+ arguments. (also in 0.6.7)
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Added a fully descriptive error message for the
+ case where Column is subclassed and _make_proxy()
+ fails to make a copy due to TypeError on the
+ constructor. The method _constructor should
+ be implemented in this case.
+
+ .. change::
+ :tags: sql
+ :tickets: 2095
+
+ Added new event "column_reflect" for Table objects.
+ Receives the info dictionary about a Column before
+ the object is generated within reflection, and allows
+ modification to the dictionary for control over
+ most aspects of the resulting Column including
+ key, name, type, info dictionary.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ To help with the "column_reflect" event being used
+ with specific Table objects instead of all instances
+ of Table, listeners can be added to a Table object
+ inline with its construction using a new argument
+ "listeners", a list of tuples of the form
+ (<eventname>, <fn>), which are applied to the Table
+ before the reflection process begins.
+
+ .. change::
+ :tags: sql
+ :tickets: 2085
+
+ Added new generic function "next_value()", accepts
+ a Sequence object as its argument and renders the
+ appropriate "next value" generation string on the
+ target platform, if supported. Also provides
+ ".next_value()" method on Sequence itself.
+
+ .. change::
+ :tags: sql
+ :tickets: 2084
+
+ func.next_value() or other SQL expression can
+ be embedded directly into an insert() construct,
+ and if implicit or explicit "returning" is used
+ in conjunction with a primary key column,
+ the newly generated value will be present in
+ result.inserted_primary_key.
+
+ .. change::
+ :tags: sql
+ :tickets: 2089
+
+ Added accessors to ResultProxy "returns_rows",
+ "is_insert" (also in 0.6.7)
+
+ .. change::
+ :tags: engine
+ :tickets: 2097
+
+ Fixed AssertionPool regression bug.
+
+ .. change::
+ :tags: engine
+ :tickets: 2060
+
+ Changed exception raised to ArgumentError when an
+ invalid dialect is specified.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2092
+
+ Added RESERVED_WORDS for postgresql dialect.
+ (also in 0.6.7)
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2073
+
+ Fixed the BIT type to allow a "length" parameter, "varying"
+ parameter. Reflection also fixed.
+ (also in 0.6.7)
+
+ .. change::
+ :tags: mssql
+ :tickets: 2071
+
+ Rewrote the query used to get the definition of a view,
+ typically when using the Inspector interface, to
+ use sys.sql_modules instead of the information schema,
+ thereby allowing views definitions longer than 4000
+ characters to be fully returned.
+ (also in 0.6.7)
+
+ .. change::
+ :tags: firebird
+ :tickets: 2083
+
+ The "implicit_returning" flag on create_engine() is
+ honored if set to False. (also in 0.6.7)
+
+ .. change::
+ :tags: informix
+ :tickets: 2092
+
+ Added RESERVED_WORDS informix dialect.
+ (also in 0.6.7)
+
+ .. change::
+ :tags: ext
+ :tickets: 2090
+
+ The horizontal_shard ShardedSession class accepts the common
+ Session argument "query_cls" as a constructor argument,
+ to enable further subclassing of ShardedQuery. (also in 0.6.7)
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ Updated the association, association proxy examples
+ to use declarative, added a new example
+ dict_of_sets_with_default.py, a "pushing the envelope"
+ example of association proxy.
+
+ .. change::
+ :tags: examples
+ :tickets: 2090
+
+ The Beaker caching example allows a "query_cls" argument
+ to the query_callable() function.
+ (also in 0.6.7)
+
+.. changelog::
+ :version: 0.7.0b2
+ :released: Sat Feb 19 2011
+
+ .. change::
+ :tags: orm
+ :tickets: 2053
+
+ Fixed bug whereby Session.merge() would call the
+ load() event with one too few arguments.
+
+ .. change::
+ :tags: orm
+ :tickets: 2052
+
+ Added logic which prevents the generation of
+ events from a MapperExtension or SessionExtension
+ from generating do-nothing events for all the methods
+ not overridden.
+
+ .. change::
+ :tags: declarative
+ :tickets: 2058
+
+ Fixed regression whereby composite() with
+ Column objects placed inline would fail
+ to initialize. The Column objects can now
+ be inline with the composite() or external
+ and pulled in via name or object ref.
+
+ .. change::
+ :tags: declarative
+ :tickets: 2061
+
+ Fix error message referencing old @classproperty
+ name to reference @declared_attr
+ (also in 0.6.7)
+
+ .. change::
+ :tags: declarative
+ :tickets: 1468
+
+ the dictionary at the end of the __table_args__
+ tuple is now optional.
+
+ .. change::
+ :tags: sql
+ :tickets: 2059
+
+ Renamed the EngineEvents event class to
+ ConnectionEvents. As these classes are never
+ accessed directly by end-user code, this strictly
+ is a documentation change for end users. Also
+ simplified how events get linked to engines
+ and connections internally.
+
+ .. change::
+ :tags: sql
+ :tickets: 2055
+
+ The Sequence() construct, when passed a MetaData()
+ object via its 'metadata' argument, will be
+ included in CREATE/DROP statements within
+ metadata.create_all() and metadata.drop_all(),
+ including "checkfirst" logic.
+
+ .. change::
+ :tags: sql
+ :tickets: 2064
+
+ The Column.references() method now returns True
+ if it has a foreign key referencing the
+ given column exactly, not just it's parent
+ table.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2065
+
+ Fixed regression from 0.6 where SMALLINT and
+ BIGINT types would both generate SERIAL
+ on an integer PK column, instead of
+ SMALLINT and BIGSERIAL
+
+ .. change::
+ :tags: ext
+ :tickets: 2054
+
+ Association proxy now has correct behavior for
+ any(), has(), and contains() when proxying
+ a many-to-one scalar attribute to a one-to-many
+ collection (i.e. the reverse of the 'typical'
+ association proxy use case)
+
+ .. change::
+ :tags: examples
+ :tickets:
+
+ Beaker example now takes into account 'limit'
+ and 'offset', bind params within embedded
+ FROM clauses (like when you use union() or
+ from_self()) when generating a cache key.
+
+.. changelog::
+ :version: 0.7.0b1
+ :released: Sat Feb 12 2011
+
+ .. change::
+ :tags:
+ :tickets:
+
+ Detailed descriptions of each change below are
+ described at:
+ http://www.sqlalchemy.org/trac/wiki/07Migration
+
+ .. change::
+ :tags: general
+ :tickets: 1902
+
+ New event system, supercedes all extensions, listeners,
+ etc.
+
+ .. change::
+ :tags: general
+ :tickets: 1926
+
+ Logging enhancements
+
+ .. change::
+ :tags: general
+ :tickets: 1949
+
+ Setup no longer installs a Nose plugin
+
+ .. change::
+ :tags: general
+ :tickets:
+
+ The "sqlalchemy.exceptions" alias in sys.modules
+ has been removed. Base SQLA exceptions are
+ available via "from sqlalchemy import exc".
+ The "exceptions" alias for "exc" remains in
+ "sqlalchemy" for now, it's just not patched into
+ sys.modules.
+
+ .. change::
+ :tags: orm
+ :tickets: 1923
+
+ More succinct form of query.join(target, onclause)
+
+ .. change::
+ :tags: orm
+ :tickets: 1903
+
+ Hybrid Attributes, implements/supercedes synonym()
+
+ .. change::
+ :tags: orm
+ :tickets: 2008
+
+ Rewrite of composites
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Mutation Event Extension, supercedes "mutable=True"
+
+ .. change::
+ :tags: orm
+ :tickets: 1980
+
+ PickleType and ARRAY mutability turned off by default
+
+ .. change::
+ :tags: orm
+ :tickets: 1895
+
+ Simplified polymorphic_on assignment
+
+ .. change::
+ :tags: orm
+ :tickets: 1912
+
+ Flushing of Orphans that have no parent is allowed
+
+ .. change::
+ :tags: orm
+ :tickets: 2041
+
+ Adjusted flush accounting step to occur before
+ the commit in the case of autocommit=True. This allows
+ autocommit=True to work appropriately with
+ expire_on_commit=True, and also allows post-flush session
+ hooks to operate in the same transactional context
+ as when autocommit=False.
+
+ .. change::
+ :tags: orm
+ :tickets: 1973
+
+ Warnings generated when collection members, scalar referents
+ not part of the flush
+
+ .. change::
+ :tags: orm
+ :tickets: 1876
+
+ Non-`Table`-derived constructs can be mapped
+
+ .. change::
+ :tags: orm
+ :tickets: 1942
+
+ Tuple label names in Query Improved
+
+ .. change::
+ :tags: orm
+ :tickets: 1892
+
+ Mapped column attributes reference the most specific
+ column first
+
+ .. change::
+ :tags: orm
+ :tickets: 1896
+
+ Mapping to joins with two or more same-named columns
+ requires explicit declaration
+
+ .. change::
+ :tags: orm
+ :tickets: 1875
+
+ Mapper requires that polymorphic_on column be present
+ in the mapped selectable
+
+ .. change::
+ :tags: orm
+ :tickets: 1966
+
+ compile_mappers() renamed configure_mappers(), simplified
+ configuration internals
+
+ .. change::
+ :tags: orm
+ :tickets: 2018
+
+ the aliased() function, if passed a SQL FromClause element
+ (i.e. not a mapped class), will return element.alias()
+ instead of raising an error on AliasedClass.
+
+ .. change::
+ :tags: orm
+ :tickets: 2027
+
+ Session.merge() will check the version id of the incoming
+ state against that of the database, assuming the mapping
+ uses version ids and incoming state has a version_id
+ assigned, and raise StaleDataError if they don't
+ match.
+
+ .. change::
+ :tags: orm
+ :tickets: 1996
+
+ Session.connection(), Session.execute() accept 'bind',
+ to allow execute/connection operations to participate
+ in the open transaction of an engine explicitly.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ Query.join(), Query.outerjoin(), eagerload(),
+ eagerload_all(), others no longer allow lists
+ of attributes as arguments (i.e. option([x, y, z])
+ form, deprecated since 0.5)
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ ScopedSession.mapper is removed (deprecated since 0.5).
+
+ .. change::
+ :tags: orm
+ :tickets: 2031
+
+ Horizontal shard query places 'shard_id' in
+ context.attributes where it's accessible by the
+ "load()" event.
+
+ .. change::
+ :tags: orm
+ :tickets: 2032
+
+ A single contains_eager() call across
+ multiple entities will indicate all collections
+ along that path should load, instead of requiring
+ distinct contains_eager() calls for each endpoint
+ (which was never correctly documented).
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ The "name" field used in orm.aliased() now renders
+ in the resulting SQL statement.
+
+ .. change::
+ :tags: orm
+ :tickets: 1473
+
+ Session weak_instance_dict=False is deprecated.
+
+ .. change::
+ :tags: orm
+ :tickets: 2046
+
+ An exception is raised in the unusual case that an
+ append or similar event on a collection occurs after
+ the parent object has been dereferenced, which
+ prevents the parent from being marked as "dirty"
+ in the session. Was a warning in 0.6.6.
+
+ .. change::
+ :tags: orm
+ :tickets: 1069
+
+ Query.distinct() now accepts column expressions
+ as *args, interpreted by the Postgresql dialect
+ as DISTINCT ON (<expr>).
+
+ .. change::
+ :tags: orm
+ :tickets: 2049
+
+ Additional tuning to "many-to-one" relationship
+ loads during a flush(). A change in version 0.6.6
+ ([ticket:2002]) required that more "unnecessary" m2o
+ loads during a flush could occur. Extra loading modes have
+ been added so that the SQL emitted in this
+ specific use case is trimmed back, while still
+ retrieving the information the flush needs in order
+ to not miss anything.
+
+ .. change::
+ :tags: orm
+ :tickets:
+
+ the value of "passive" as passed to
+ attributes.get_history() should be one of the
+ constants defined in the attributes package. Sending
+ True or False is deprecated.
+
+ .. change::
+ :tags: orm
+ :tickets: 2030
+
+ Added a `name` argument to `Query.subquery()`, to allow
+ a fixed name to be assigned to the alias object. (also in 0.6.7)
+
+ .. change::
+ :tags: orm
+ :tickets: 2019
+
+ A warning is emitted when a joined-table inheriting mapper
+ has no primary keys on the locally mapped table
+ (but has pks on the superclass table).
+ (also in 0.6.7)
+
+ .. change::
+ :tags: orm
+ :tickets: 2038
+
+ Fixed bug where "middle" class in a polymorphic hierarchy
+ would have no 'polymorphic_on' column if it didn't also
+ specify a 'polymorphic_identity', leading to strange
+ errors upon refresh, wrong class loaded when querying
+ from that target. Also emits the correct WHERE criterion
+ when using single table inheritance.
+ (also in 0.6.7)
+
+ .. change::
+ :tags: orm
+ :tickets: 1995
+
+ Fixed bug where a column with a SQL or server side default
+ that was excluded from a mapping with include_properties
+ or exclude_properties would result in UnmappedColumnError. (also in 0.6.7)
+
+ .. change::
+ :tags: orm
+ :tickets: 2046
+
+ A warning is emitted in the unusual case that an
+ append or similar event on a collection occurs after
+ the parent object has been dereferenced, which
+ prevents the parent from being marked as "dirty"
+ in the session. This will be an exception in 0.7. (also in 0.6.7)
+
+ .. change::
+ :tags: declarative
+ :tickets: 2050
+
+ Added an explicit check for the case that the name
+ 'metadata' is used for a column attribute on a
+ declarative class. (also in 0.6.7)
+
+ .. change::
+ :tags: sql
+ :tickets: 1844
+
+ Added over() function, method to FunctionElement
+ classes, produces the _Over() construct which
+ in turn generates "window functions", i.e.
+ "<window function> OVER (PARTITION BY <partition by>,
+ ORDER BY <order by>)".
+
+ .. change::
+ :tags: sql
+ :tickets: 805
+
+ LIMIT/OFFSET clauses now use bind parameters
+
+ .. change::
+ :tags: sql
+ :tickets: 1069
+
+ select.distinct() now accepts column expressions
+ as *args, interpreted by the Postgresql dialect
+ as DISTINCT ON (<expr>). Note this was already
+ available via passing a list to the `distinct`
+ keyword argument to select().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ select.prefix_with() accepts multiple expressions
+ (i.e. *expr), 'prefix' keyword argument to select()
+ accepts a list or tuple.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Passing a string to the `distinct` keyword argument
+ of `select()` for the purpose of emitting special
+ MySQL keywords (DISTINCTROW etc.) is deprecated -
+ use `prefix_with()` for this.
+
+ .. change::
+ :tags: sql
+ :tickets: 2006, 2005
+
+ TypeDecorator works with primary key columns
+
+ .. change::
+ :tags: sql
+ :tickets: 1897
+
+ DDL() constructs now escape percent signs
+
+ .. change::
+ :tags: sql
+ :tickets: 1917, 1893
+
+ Table.c / MetaData.tables refined a bit, don't allow direct
+ mutation
+
+ .. change::
+ :tags: sql
+ :tickets: 1950
+
+ Callables passed to `bindparam()` don't get evaluated
+
+ .. change::
+ :tags: sql
+ :tickets: 1870
+
+ types.type_map is now private, types._type_map
+
+ .. change::
+ :tags: sql
+ :tickets: 1982
+
+ Non-public Pool methods underscored
+
+ .. change::
+ :tags: sql
+ :tickets: 723
+
+ Added NULLS FIRST and NULLS LAST support. It's implemented
+ as an extension to the asc() and desc() operators, called
+ nullsfirst() and nullslast().
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ The Index() construct can be created inline with a Table
+ definition, using strings as column names, as an alternative
+ to the creation of the index outside of the Table.
+
+ .. change::
+ :tags: sql
+ :tickets: 2001
+
+ execution_options() on Connection accepts
+ "isolation_level" argument, sets transaction isolation
+ level for that connection only until returned to the
+ connection pool, for thsoe backends which support it
+ (SQLite, Postgresql)
+
+ .. change::
+ :tags: sql
+ :tickets: 2005
+
+ A TypeDecorator of Integer can be used with a primary key
+ column, and the "autoincrement" feature of various dialects
+ as well as the "sqlite_autoincrement" flag will honor
+ the underlying database type as being Integer-based.
+
+ .. change::
+ :tags: sql
+ :tickets: 2020, 2021
+
+ Established consistency when server_default is present
+ on an Integer PK column. SQLA doesn't pre-fetch these,
+ nor do they come back in cursor.lastrowid (DBAPI).
+ Ensured all backends consistently return None
+ in result.inserted_primary_key for these. Regarding
+ reflection for this case, reflection of an int PK col
+ with a server_default sets the "autoincrement" flag to False,
+ except in the case of a PG SERIAL col where we detected a
+ sequence default.
+
+ .. change::
+ :tags: sql
+ :tickets: 2006
+
+ Result-row processors are applied to pre-executed SQL
+ defaults, as well as cursor.lastrowid, when determining
+ the contents of result.inserted_primary_key.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ Bind parameters present in the "columns clause" of a select
+ are now auto-labeled like other "anonymous" clauses,
+ which among other things allows their "type" to be meaningful
+ when the row is fetched, as in result row processors.
+
+ .. change::
+ :tags: sql
+ :tickets:
+
+ TypeDecorator is present in the "sqlalchemy" import space.
+
+ .. change::
+ :tags: sql
+ :tickets: 2015
+
+ Non-DBAPI errors which occur in the scope of an `execute()`
+ call are now wrapped in sqlalchemy.exc.StatementError,
+ and the text of the SQL statement and repr() of params
+ is included. This makes it easier to identify statement
+ executions which fail before the DBAPI becomes
+ involved.
+
+ .. change::
+ :tags: sql
+ :tickets: 2048
+
+ The concept of associating a ".bind" directly with a
+ ClauseElement has been explicitly moved to Executable,
+ i.e. the mixin that describes ClauseElements which represent
+ engine-executable constructs. This change is an improvement
+ to internal organization and is unlikely to affect any
+ real-world usage.
+
+ .. change::
+ :tags: sql
+ :tickets: 2028
+
+ Column.copy(), as used in table.tometadata(), copies the
+ 'doc' attribute. (also in 0.6.7)
+
+ .. change::
+ :tags: sql
+ :tickets: 2023
+
+ Added some defs to the resultproxy.c extension so that
+ the extension compiles and runs on Python 2.4. (also in 0.6.7)
+
+ .. change::
+ :tags: sql
+ :tickets: 2042
+
+ The compiler extension now supports overriding the default
+ compilation of expression._BindParamClause including that
+ the auto-generated binds within the VALUES/SET clause
+ of an insert()/update() statement will also use the new
+ compilation rules. (also in 0.6.7)
+
+ .. change::
+ :tags: sql
+ :tickets: 1921
+
+ SQLite dialect now uses `NullPool` for file-based databases
+
+ .. change::
+ :tags: sql
+ :tickets: 2036
+
+ The path given as the location of a sqlite database is now
+ normalized via os.path.abspath(), so that directory changes
+ within the process don't affect the ultimate location
+ of a relative file path.
+
+ .. change::
+ :tags: postgresql
+ :tickets: 1083
+
+ When explicit sequence execution derives the name
+ of the auto-generated sequence of a SERIAL column,
+ which currently only occurs if implicit_returning=False,
+ now accommodates if the table + column name is greater
+ than 63 characters using the same logic Postgresql uses. (also in 0.6.7)
+
+ .. change::
+ :tags: postgresql
+ :tickets: 2044
+
+ Added an additional libpq message to the list of "disconnect"
+ exceptions, "could not receive data from server" (also in 0.6.7)
+
+ .. change::
+ :tags: mssql
+ :tickets: 1833
+
+ the String/Unicode types, and their counterparts VARCHAR/
+ NVARCHAR, emit "max" as the length when no length is
+ specified, so that the default length, normally '1'
+ as per SQL server documentation, is instead
+ 'unbounded'. This also occurs for the VARBINARY type..
+
+ This behavior makes these types more closely compatible
+ with Postgresql's VARCHAR type which is similarly unbounded
+ when no length is specified.
+
+ .. change::
+ :tags: mysql
+ :tickets: 1991
+
+ New DBAPI support for pymysql, a pure Python port
+ of MySQL-python.
+
+ .. change::
+ :tags: mysql
+ :tickets: 2047
+
+ oursql dialect accepts the same "ssl" arguments in
+ create_engine() as that of MySQLdb.
+ (also in 0.6.7)
+
+ .. change::
+ :tags: firebird
+ :tickets: 1885
+
+ Some adjustments so that Interbase is supported as well.
+ FB/Interbase version idents are parsed into a structure
+ such as (8, 1, 1, 'interbase') or (2, 1, 588, 'firebird')
+ so they can be distinguished.
--- /dev/null
+.. _changelog_toplevel:
+
+Changes and Migration
+=====================
+
+Migration Guides
+----------------
+
+SQLAlchemy migration guides are now available within the main documentation.
+
+.. toctree::
+ :maxdepth: 1
+
+ migration_07
+ migration_06
+ migration_05
+ migration_04
+
+Change logs
+-----------
+
+SQLAlchemy changelogs are now available within the main documentation.
+
+.. toctree::
+ :maxdepth: 2
+
+ changelog_07
+ changelog_06
+ changelog_05
+ changelog_04
+ changelog_03
+ changelog_02
+ changelog_01
+
--- /dev/null
+=============================
+What's new in SQLAlchemy 0.4?
+=============================
+
+.. admonition:: About this Document
+
+ This document describes changes between SQLAlchemy version 0.3,
+ last released October 14, 2007, and SQLAlchemy version 0.4,
+ last released October 12, 2008.
+
+ Document date: March 21, 2008
+
+First Things First
+==================
+
+If you're using any ORM features, make sure you import from
+``sqlalchemy.orm``:
+
+::
+
+ from sqlalchemy import *
+ from sqlalchemy.orm import *
+
+Secondly, anywhere you used to say ``engine=``,
+``connectable=``, ``bind_to=``, ``something.engine``,
+``metadata.connect()``, use ``bind``:
+
+::
+
+ myengine = create_engine('sqlite://')
+
+ meta = MetaData(myengine)
+
+ meta2 = MetaData()
+ meta2.bind = myengine
+
+ session = create_session(bind=myengine)
+
+ statement = select([table], bind=myengine)
+
+Got those ? Good! You're now (95%) 0.4 compatible. If
+you're using 0.3.10, you can make these changes immediately;
+they'll work there too.
+
+Module Imports
+==============
+
+In 0.3, "``from sqlachemy import *``" would import all of
+sqlachemy's sub-modules into your namespace. Version 0.4 no
+longer imports sub-modules into the namespace. This may mean
+you need to add extra imports into your code.
+
+In 0.3, this code worked:
+
+::
+
+ from sqlalchemy import *
+
+ class UTCDateTime(types.TypeDecorator):
+ pass
+
+In 0.4, one must do:
+
+::
+
+ from sqlalchemy import *
+ from sqlalchemy import types
+
+ class UTCDateTime(types.TypeDecorator):
+ pass
+
+Object Relational Mapping
+=========================
+
+Querying
+--------
+
+New Query API
+^^^^^^^^^^^^^
+
+Query is standardized on the generative interface (old
+interface is still there, just deprecated). While most of
+the generative interface is available in 0.3, the 0.4 Query
+has the inner guts to match the generative outside, and has
+a lot more tricks. All result narrowing is via ``filter()``
+and ``filter_by()``, limiting/offset is either through array
+slices or ``limit()``/``offset()``, joining is via
+``join()`` and ``outerjoin()`` (or more manually, through
+``select_from()`` as well as manually-formed criteria).
+
+To avoid deprecation warnings, you must make some changes to
+your 03 code
+
+User.query.get_by( \**kwargs )
+
+::
+
+ User.query.filter_by(**kwargs).first()
+
+User.query.select_by( \**kwargs )
+
+::
+
+ User.query.filter_by(**kwargs).all()
+
+User.query.select()
+
+::
+
+ User.query.filter(xxx).all()
+
+New Property-Based Expression Constructs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By far the most palpable difference within the ORM is that
+you can now construct your query criterion using class-based
+attributes directly. The ".c." prefix is no longer needed
+when working with mapped classes:
+
+::
+
+ session.query(User).filter(and_(User.name == 'fred', User.id > 17))
+
+While simple column-based comparisons are no big deal, the
+class attributes have some new "higher level" constructs
+available, including what was previously only available in
+``filter_by()``:
+
+::
+
+ # comparison of scalar relations to an instance
+ filter(Address.user == user)
+
+ # return all users who contain a particular address
+ filter(User.addresses.contains(address))
+
+ # return all users who *dont* contain the address
+ filter(~User.address.contains(address))
+
+ # return all users who contain a particular address with
+ # the email_address like '%foo%'
+ filter(User.addresses.any(Address.email_address.like('%foo%')))
+
+ # same, email address equals 'foo@bar.com'. can fall back to keyword
+ # args for simple comparisons
+ filter(User.addresses.any(email_address = 'foo@bar.com'))
+
+ # return all Addresses whose user attribute has the username 'ed'
+ filter(Address.user.has(name='ed'))
+
+ # return all Addresses whose user attribute has the username 'ed'
+ # and an id > 5 (mixing clauses with kwargs)
+ filter(Address.user.has(User.id > 5, name='ed'))
+
+The ``Column`` collection remains available on mapped
+classes in the ``.c`` attribute. Note that property-based
+expressions are only available with mapped properties of
+mapped classes. ``.c`` is still used to access columns in
+regular tables and selectable objects produced from SQL
+Expressions.
+
+Automatic Join Aliasing
+^^^^^^^^^^^^^^^^^^^^^^^
+
+We've had join() and outerjoin() for a while now:
+
+::
+
+ session.query(Order).join('items')...
+
+Now you can alias them:
+
+::
+
+ session.query(Order).join('items', aliased=True).
+ filter(Item.name='item 1').join('items', aliased=True).filter(Item.name=='item 3')
+
+The above will create two joins from orders->items using
+aliases. the ``filter()`` call subsequent to each will
+adjust its table criterion to that of the alias. To get at
+the ``Item`` objects, use ``add_entity()`` and target each
+join with an ``id``:
+
+::
+
+ session.query(Order).join('items', id='j1', aliased=True).
+ filter(Item.name == 'item 1').join('items', aliased=True, id='j2').
+ filter(Item.name == 'item 3').add_entity(Item, id='j1').add_entity(Item, id='j2')
+
+Returns tuples in the form: ``(Order, Item, Item)``.
+
+Self-referential Queries
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+So query.join() can make aliases now. What does that give
+us ? Self-referential queries ! Joins can be done without
+any ``Alias`` objects:
+
+::
+
+ # standard self-referential TreeNode mapper with backref
+ mapper(TreeNode, tree_nodes, properties={
+ 'children':relation(TreeNode, backref=backref('parent', remote_side=tree_nodes.id))
+ })
+
+ # query for node with child containing "bar" two levels deep
+ session.query(TreeNode).join(["children", "children"], aliased=True).filter_by(name='bar')
+
+To add criterion for each table along the way in an aliased
+join, you can use ``from_joinpoint`` to keep joining against
+the same line of aliases:
+
+::
+
+ # search for the treenode along the path "n1/n12/n122"
+
+ # first find a Node with name="n122"
+ q = sess.query(Node).filter_by(name='n122')
+
+ # then join to parent with "n12"
+ q = q.join('parent', aliased=True).filter_by(name='n12')
+
+ # join again to the next parent with 'n1'. use 'from_joinpoint'
+ # so we join from the previous point, instead of joining off the
+ # root table
+ q = q.join('parent', aliased=True, from_joinpoint=True).filter_by(name='n1')
+
+ node = q.first()
+
+``query.populate_existing()``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The eager version of ``query.load()`` (or
+``session.refresh()``). Every instance loaded from the
+query, including all eagerly loaded items, get refreshed
+immediately if already present in the session:
+
+::
+
+ session.query(Blah).populate_existing().all()
+
+Relations
+---------
+
+SQL Clauses Embedded in Updates/Inserts
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For inline execution of SQL clauses, embedded right in the
+UPDATE or INSERT, during a ``flush()``:
+
+::
+
+
+ myobject.foo = mytable.c.value + 1
+
+ user.pwhash = func.md5(password)
+
+ order.hash = text("select hash from hashing_table")
+
+The column-attribute is set up with a deferred loader after
+the operation, so that it issues the SQL to load the new
+value when you next access.
+
+Self-referential and Cyclical Eager Loading
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Since our alias-fu has improved, ``relation()`` can join
+along the same table \*any number of times*; you tell it how
+deep you want to go. Lets show the self-referential
+``TreeNode`` more clearly:
+
+::
+
+ nodes = Table('nodes', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('parent_id', Integer, ForeignKey('nodes.id')),
+ Column('name', String(30)))
+
+ class TreeNode(object):
+ pass
+
+ mapper(TreeNode, nodes, properties={
+ 'children':relation(TreeNode, lazy=False, join_depth=3)
+ })
+
+So what happens when we say:
+
+::
+
+ create_session().query(TreeNode).all()
+
+? A join along aliases, three levels deep off the parent:
+
+::
+
+ SELECT
+ nodes_3.id AS nodes_3_id, nodes_3.parent_id AS nodes_3_parent_id, nodes_3.name AS nodes_3_name,
+ nodes_2.id AS nodes_2_id, nodes_2.parent_id AS nodes_2_parent_id, nodes_2.name AS nodes_2_name,
+ nodes_1.id AS nodes_1_id, nodes_1.parent_id AS nodes_1_parent_id, nodes_1.name AS nodes_1_name,
+ nodes.id AS nodes_id, nodes.parent_id AS nodes_parent_id, nodes.name AS nodes_name
+ FROM nodes LEFT OUTER JOIN nodes AS nodes_1 ON nodes.id = nodes_1.parent_id
+ LEFT OUTER JOIN nodes AS nodes_2 ON nodes_1.id = nodes_2.parent_id
+ LEFT OUTER JOIN nodes AS nodes_3 ON nodes_2.id = nodes_3.parent_id
+ ORDER BY nodes.oid, nodes_1.oid, nodes_2.oid, nodes_3.oid
+
+Notice the nice clean alias names too. The joining doesn't
+care if it's against the same immediate table or some other
+object which then cycles back to the beginining. Any kind
+of chain of eager loads can cycle back onto itself when
+``join_depth`` is specified. When not present, eager
+loading automatically stops when it hits a cycle.
+
+Composite Types
+^^^^^^^^^^^^^^^
+
+This is one from the Hibernate camp. Composite Types let
+you define a custom datatype that is composed of more than
+one column (or one column, if you wanted). Lets define a
+new type, ``Point``. Stores an x/y coordinate:
+
+::
+
+ class Point(object):
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+ def __composite_values__(self):
+ return self.x, self.y
+ def __eq__(self, other):
+ return other.x == self.x and other.y == self.y
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+The way the ``Point`` object is defined is specific to a
+custom type; constructor takes a list of arguments, and the
+``__composite_values__()`` method produces a sequence of
+those arguments. The order will match up to our mapper, as
+we'll see in a moment.
+
+Let's create a table of vertices storing two points per row:
+
+::
+
+ vertices = Table('vertices', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('x1', Integer),
+ Column('y1', Integer),
+ Column('x2', Integer),
+ Column('y2', Integer),
+ )
+
+Then, map it ! We'll create a ``Vertex`` object which
+stores two ``Point`` objects:
+
+::
+
+ class Vertex(object):
+ def __init__(self, start, end):
+ self.start = start
+ self.end = end
+
+ mapper(Vertex, vertices, properties={
+ 'start':composite(Point, vertices.c.x1, vertices.c.y1),
+ 'end':composite(Point, vertices.c.x2, vertices.c.y2)
+ })
+
+Once you've set up your composite type, it's usable just
+like any other type:
+
+::
+
+
+ v = Vertex(Point(3, 4), Point(26,15))
+ session.save(v)
+ session.flush()
+
+ # works in queries too
+ q = session.query(Vertex).filter(Vertex.start == Point(3, 4))
+
+If you'd like to define the way the mapped attributes
+generate SQL clauses when used in expressions, create your
+own ``sqlalchemy.orm.PropComparator`` subclass, defining any
+of the common operators (like ``__eq__()``, ``__le__()``,
+etc.), and send it in to ``composite()``. Composite types
+work as primary keys too, and are usable in ``query.get()``:
+
+::
+
+ # a Document class which uses a composite Version
+ # object as primary key
+ document = query.get(Version(1, 'a'))
+
+``dynamic_loader()`` relations
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A ``relation()`` that returns a live ``Query`` object for
+all read operations. Write operations are limited to just
+``append()`` and ``remove()``, changes to the collection are
+not visible until the session is flushed. This feature is
+particularly handy with an "autoflushing" session which will
+flush before each query.
+
+::
+
+ mapper(Foo, foo_table, properties={
+ 'bars':dynamic_loader(Bar, backref='foo', <other relation() opts>)
+ })
+
+ session = create_session(autoflush=True)
+ foo = session.query(Foo).first()
+
+ foo.bars.append(Bar(name='lala'))
+
+ for bar in foo.bars.filter(Bar.name=='lala'):
+ print bar
+
+ session.commit()
+
+New Options: ``undefer_group()``, ``eagerload_all()``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A couple of query options which are handy.
+``undefer_group()`` marks a whole group of "deferred"
+columns as undeferred:
+
+::
+
+ mapper(Class, table, properties={
+ 'foo' : deferred(table.c.foo, group='group1'),
+ 'bar' : deferred(table.c.bar, group='group1'),
+ 'bat' : deferred(table.c.bat, group='group1'),
+ )
+
+ session.query(Class).options(undefer_group('group1')).filter(...).all()
+
+and ``eagerload_all()`` sets a chain of attributes to be
+eager in one pass:
+
+::
+
+ mapper(Foo, foo_table, properties={
+ 'bar':relation(Bar)
+ })
+ mapper(Bar, bar_table, properties={
+ 'bat':relation(Bat)
+ })
+ mapper(Bat, bat_table)
+
+ # eager load bar and bat
+ session.query(Foo).options(eagerload_all('bar.bat')).filter(...).all()
+
+New Collection API
+^^^^^^^^^^^^^^^^^^
+
+Collections are no longer proxied by an
+{{{InstrumentedList}}} proxy, and access to members, methods
+and attributes is direct. Decorators now intercept objects
+entering and leaving the collection, and it is now possible
+to easily write a custom collection class that manages its
+own membership. Flexible decorators also replace the named
+method interface of custom collections in 0.3, allowing any
+class to be easily adapted to use as a collection container.
+
+Dictionary-based collections are now much easier to use and
+fully ``dict``-like. Changing ``__iter__`` is no longer
+needed for ``dict``s, and new built-in ``dict`` types cover
+many needs:
+
+::
+
+ # use a dictionary relation keyed by a column
+ relation(Item, collection_class=column_mapped_collection(items.c.keyword))
+ # or named attribute
+ relation(Item, collection_class=attribute_mapped_collection('keyword'))
+ # or any function you like
+ relation(Item, collection_class=mapped_collection(lambda entity: entity.a + entity.b))
+
+Existing 0.3 ``dict``-like and freeform object derived
+collection classes will need to be updated for the new API.
+In most cases this is simply a matter of adding a couple
+decorators to the class definition.
+
+Mapped Relations from External Tables/Subqueries
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This feature quietly appeared in 0.3 but has been improved
+in 0.4 thanks to better ability to convert subqueries
+against a table into subqueries against an alias of that
+table; this is key for eager loading, aliased joins in
+queries, etc. It reduces the need to create mappers against
+select statements when you just need to add some extra
+columns or subqueries:
+
+::
+
+ mapper(User, users, properties={
+ 'fullname': column_property((users.c.firstname + users.c.lastname).label('fullname')),
+ 'numposts': column_property(
+ select([func.count(1)], users.c.id==posts.c.user_id).correlate(users).label('posts')
+ )
+ })
+
+a typical query looks like:
+
+::
+
+ SELECT (SELECT count(1) FROM posts WHERE users.id = posts.user_id) AS count,
+ users.firstname || users.lastname AS fullname,
+ users.id AS users_id, users.firstname AS users_firstname, users.lastname AS users_lastname
+ FROM users ORDER BY users.oid
+
+Horizontal Scaling (Sharding) API
+---------------------------------
+
+[browser:/sqlalchemy/trunk/examples/sharding/attribute_shard
+.py]
+
+Sessions
+--------
+
+New Session Create Paradigm; SessionContext, assignmapper Deprecated
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+That's right, the whole shebang is being replaced with two
+configurational functions. Using both will produce the most
+0.1-ish feel we've had since 0.1 (i.e., the least amount of
+typing).
+
+Configure your own ``Session`` class right where you define
+your ``engine`` (or anywhere):
+
+::
+
+ from sqlalchemy import create_engine
+ from sqlalchemy.orm import sessionmaker
+
+ engine = create_engine('myengine://')
+ Session = sessionmaker(bind=engine, autoflush=True, transactional=True)
+
+ # use the new Session() freely
+ sess = Session()
+ sess.save(someobject)
+ sess.flush()
+
+
+If you need to post-configure your Session, say with an
+engine, add it later with ``configure()``:
+
+::
+
+ Session.configure(bind=create_engine(...))
+
+All the behaviors of ``SessionContext`` and the ``query``
+and ``__init__`` methods of ``assignmapper`` are moved into
+the new ``scoped_session()`` function, which is compatible
+with both ``sessionmaker`` as well as ``create_session()``:
+
+::
+
+ from sqlalchemy.orm import scoped_session, sessionmaker
+
+ Session = scoped_session(sessionmaker(autoflush=True, transactional=True))
+ Session.configure(bind=engine)
+
+ u = User(name='wendy')
+
+ sess = Session()
+ sess.save(u)
+ sess.commit()
+
+ # Session constructor is thread-locally scoped. Everyone gets the same
+ # Session in the thread when scope="thread".
+ sess2 = Session()
+ assert sess is sess2
+
+
+When using a thread-local ``Session``, the returned class
+has all of ``Session's`` interface implemented as
+classmethods, and "assignmapper"'s functionality is
+available using the ``mapper`` classmethod. Just like the
+old ``objectstore`` days....
+
+::
+
+
+ # "assignmapper"-like functionality available via ScopedSession.mapper
+ Session.mapper(User, users_table)
+
+ u = User(name='wendy')
+
+ Session.commit()
+
+
+Sessions are again Weak Referencing By Default
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The weak_identity_map flag is now set to ``True`` by default
+on Session. Instances which are externally deferenced and
+fall out of scope are removed from the session
+automatically. However, items which have "dirty" changes
+present will remain strongly referenced until those changes
+are flushed at which case the object reverts to being weakly
+referenced (this works for 'mutable' types, like picklable
+attributes, as well). Setting weak_identity_map to
+``False`` restores the old strong-referencing behavior for
+those of you using the session like a cache.
+
+Auto-Transactional Sessions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As you might have noticed above, we are calling ``commit()``
+on ``Session``. The flag ``transactional=True`` means the
+``Session`` is always in a transaction, ``commit()``
+persists permanently.
+
+Auto-Flushing Sessions
+^^^^^^^^^^^^^^^^^^^^^^
+
+Also, ``autoflush=True`` means the ``Session`` will
+``flush()`` before each ``query`` as well as when you call
+``flush()`` or ``commit()``. So now this will work:
+
+::
+
+ Session = sessionmaker(bind=engine, autoflush=True, transactional=True)
+
+ u = User(name='wendy')
+
+ sess = Session()
+ sess.save(u)
+
+ # wendy is flushed, comes right back from a query
+ wendy = sess.query(User).filter_by(name='wendy').one()
+
+Transactional methods moved onto sessions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``commit()`` and ``rollback()``, as well as ``begin()`` are
+now directly on ``Session``. No more need to use
+``SessionTransaction`` for anything (it remains in the
+background).
+
+::
+
+ Session = sessionmaker(autoflush=True, transactional=False)
+
+ sess = Session()
+ sess.begin()
+
+ # use the session
+
+ sess.commit() # commit transaction
+
+Sharing a ``Session`` with an enclosing engine-level (i.e.
+non-ORM) transaction is easy:
+
+::
+
+ Session = sessionmaker(autoflush=True, transactional=False)
+
+ conn = engine.connect()
+ trans = conn.begin()
+ sess = Session(bind=conn)
+
+ # ... session is transactional
+
+ # commit the outermost transaction
+ trans.commit()
+
+Nested Session Transactions with SAVEPOINT
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Available at the Engine and ORM level. ORM docs so far:
+
+http://www.sqlalchemy.org/docs/04/session.html#unitofwork_ma
+naging
+
+Two-Phase Commit Sessions
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Available at the Engine and ORM level. ORM docs so far:
+
+http://www.sqlalchemy.org/docs/04/session.html#unitofwork_ma
+naging
+
+Inheritance
+-----------
+
+Polymorphic Inheritance with No Joins or Unions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+New docs for inheritance: http://www.sqlalchemy.org/docs/04
+/mappers.html#advdatamapping_mapper_inheritance_joined
+
+Better Polymorphic Behavior with ``get()``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+All classes within a joined-table inheritance hierarchy get
+an ``_instance_key`` using the base class, i.e.
+``(BaseClass, (1, ), None)``. That way when you call
+``get()`` a ``Query`` against the base class, it can locate
+subclass instances in the current identity map without
+querying the database.
+
+Types
+-----
+
+Custom Subclasses of ``sqlalchemy.types.TypeDecorator``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There is a `New API <http://www.sqlalchemy.org/docs/04/types
+.html#types_custom>`_ for subclassing a TypeDecorator.
+Using the 0.3 API causes compilation errors in some cases.
+
+SQL Expressions
+===============
+
+All New, Deterministic Label/Alias Generation
+---------------------------------------------
+
+All the "anonymous" labels and aliases use a simple
+<name>_<number> format now. SQL is much easier to read and
+is compatible with plan optimizer caches. Just check out
+some of the examples in the tutorials:
+http://www.sqlalchemy.org/docs/04/ormtutorial.html
+http://www.sqlalchemy.org/docs/04/sqlexpression.html
+
+Generative select() Constructs
+------------------------------
+
+This is definitely the way to go with ``select()``. See htt
+p://www.sqlalchemy.org/docs/04/sqlexpression.html#sql_transf
+orm .
+
+New Operator System
+-------------------
+
+SQL operators and more or less every SQL keyword there is
+are now abstracted into the compiler layer. They now act
+intelligently and are type/backend aware, see: http://www.sq
+lalchemy.org/docs/04/sqlexpression.html#sql_operators
+
+All ``type`` Keyword Arguments Renamed to ``type_``
+---------------------------------------------------
+
+Just like it says:
+
+::
+
+ b = bindparam('foo', type_=String)
+
+in_ Function Changed to Accept Sequence or Selectable
+-----------------------------------------------------
+
+The in_ function now takes a sequence of values or a
+selectable as its sole argument. The previous API of passing
+in values as positional arguments still works, but is now
+deprecated. This means that
+
+::
+
+ my_table.select(my_table.c.id.in_(1,2,3)
+ my_table.select(my_table.c.id.in_(*listOfIds)
+
+should be changed to
+
+::
+
+ my_table.select(my_table.c.id.in_([1,2,3])
+ my_table.select(my_table.c.id.in_(listOfIds)
+
+Schema and Reflection
+=====================
+
+``MetaData``, ``BoundMetaData``, ``DynamicMetaData``...
+-------------------------------------------------------
+
+In the 0.3.x series, ``BoundMetaData`` and
+``DynamicMetaData`` were deprecated in favor of ``MetaData``
+and ``ThreadLocalMetaData``. The older names have been
+removed in 0.4. Updating is simple:
+
+::
+
+ +-------------------------------------+-------------------------+
+ |If You Had | Now Use |
+ +=====================================+=========================+
+ | ``MetaData`` | ``MetaData`` |
+ +-------------------------------------+-------------------------+
+ | ``BoundMetaData`` | ``MetaData`` |
+ +-------------------------------------+-------------------------+
+ | ``DynamicMetaData`` (with one | ``MetaData`` |
+ | engine or threadlocal=False) | |
+ +-------------------------------------+-------------------------+
+ | ``DynamicMetaData`` | ``ThreadLocalMetaData`` |
+ | (with different engines per thread) | |
+ +-------------------------------------+-------------------------+
+
+The seldom-used ``name`` parameter to ``MetaData`` types has
+been removed. The ``ThreadLocalMetaData`` constructor now
+takes no arguments. Both types can now be bound to an
+``Engine`` or a single ``Connection``.
+
+One Step Multi-Table Reflection
+-------------------------------
+
+You can now load table definitions and automatically create
+``Table`` objects from an entire database or schema in one
+pass:
+
+::
+
+ >>> metadata = MetaData(myengine, reflect=True)
+ >>> metadata.tables.keys()
+ ['table_a', 'table_b', 'table_c', '...']
+
+``MetaData`` also gains a ``.reflect()`` method enabling
+finer control over the loading process, including
+specification of a subset of available tables to load.
+
+SQL Execution
+=============
+
+``engine``, ``connectable``, and ``bind_to`` are all now ``bind``
+-----------------------------------------------------------------
+
+``Transactions``, ``NestedTransactions`` and ``TwoPhaseTransactions``
+---------------------------------------------------------------------
+
+Connection Pool Events
+----------------------
+
+The connection pool now fires events when new DB-API
+connections are created, checked out and checked back into
+the pool. You can use these to execute session-scoped SQL
+setup statements on fresh connections, for example.
+
+Oracle Engine Fixed
+-------------------
+
+In 0.3.11, there were bugs in the Oracle Engine on how
+Primary Keys are handled. These bugs could cause programs
+that worked fine with other engines, such as sqlite, to fail
+when using the Oracle Engine. In 0.4, the Oracle Engine has
+been reworked, fixing these Primary Key problems.
+
+Out Parameters for Oracle
+-------------------------
+
+::
+
+ result = engine.execute(text("begin foo(:x, :y, :z); end;", bindparams=[bindparam('x', Numeric), outparam('y', Numeric), outparam('z', Numeric)]), x=5)
+ assert result.out_parameters == {'y':10, 'z':75}
+
+Connection-bound ``MetaData``, ``Sessions``
+-------------------------------------------
+
+``MetaData`` and ``Session`` can be explicitly bound to a
+connection:
+
+::
+
+ conn = engine.connect()
+ sess = create_session(bind=conn)
+
+Faster, More Foolproof ``ResultProxy`` Objects
+----------------------------------------------
+
--- /dev/null
+=============================
+What's new in SQLAlchemy 0.5?
+=============================
+
+.. admonition:: About this Document
+
+ This document describes changes between SQLAlchemy version 0.4,
+ last released October 12, 2008, and SQLAlchemy version 0.5,
+ last released January 16, 2010.
+
+ Document date: August 4, 2009
+
+
+This guide documents API changes which affect users
+migrating their applications from the 0.4 series of
+SQLAlchemy to 0.5. It's also recommended for those working
+from `Essential SQLAlchemy
+<http://oreilly.com/catalog/9780596516147/>`_, which only
+covers 0.4 and seems to even have some old 0.3isms in it.
+Note that SQLAlchemy 0.5 removes many behaviors which were
+deprecated throughout the span of the 0.4 series, and also
+deprecates more behaviors specific to 0.4.
+
+Major Documentation Changes
+===========================
+
+Some sections of the documentation have been completely
+rewritten and can serve as an introduction to new ORM
+features. The ``Query`` and ``Session`` objects in
+particular have some distinct differences in API and
+behavior which fundamentally change many of the basic ways
+things are done, particularly with regards to constructing
+highly customized ORM queries and dealing with stale session
+state, commits and rollbacks.
+
+* `ORM Tutorial
+ <http://www.sqlalchemy.org/docs/05/ormtutorial.html>`_
+
+* `Session Documentation
+ <http://www.sqlalchemy.org/docs/05/session.html>`_
+
+Deprecations Source
+===================
+
+Another source of information is documented within a series
+of unit tests illustrating up to date usages of some common
+``Query`` patterns; this file can be viewed at
+[source:sqlalchemy/trunk/test/orm/test_deprecations.py].
+
+Requirements Changes
+====================
+
+* Python 2.4 or higher is required. The SQLAlchemy 0.4 line
+ is the last version with Python 2.3 support.
+
+Object Relational Mapping
+=========================
+
+* **Column level expressions within Query.** - as detailed
+ in the `tutorial
+ <http://www.sqlalchemy.org/docs/05/ormtutorial.html>`_,
+ ``Query`` has the capability to create specific SELECT
+ statements, not just those against full rows:
+
+ ::
+
+ session.query(User.name, func.count(Address.id).label("numaddresses")).join(Address).group_by(User.name)
+
+ The tuples returned by any multi-column/entity query are
+ *named*' tuples:
+
+ ::
+
+ for row in session.query(User.name, func.count(Address.id).label('numaddresses')).join(Address).group_by(User.name):
+ print "name", row.name, "number", row.numaddresses
+
+ ``Query`` has a ``statement`` accessor, as well as a
+ ``subquery()`` method which allow ``Query`` to be used to
+ create more complex combinations:
+
+ ::
+
+ subq = session.query(Keyword.id.label('keyword_id')).filter(Keyword.name.in_(['beans', 'carrots'])).subquery()
+ recipes = session.query(Recipe).filter(exists().
+ where(Recipe.id==recipe_keywords.c.recipe_id).
+ where(recipe_keywords.c.keyword_id==subq.c.keyword_id)
+ )
+
+* **Explicit ORM aliases are recommended for aliased joins**
+ - The ``aliased()`` function produces an "alias" of a
+ class, which allows fine-grained control of aliases in
+ conjunction with ORM queries. While a table-level alias
+ (i.e. ``table.alias()``) is still usable, an ORM level
+ alias retains the semantics of the ORM mapped object which
+ is significant for inheritance mappings, options, and
+ other scenarios. E.g.:
+
+ ::
+
+ Friend = aliased(Person)
+ session.query(Person, Friend).join((Friend, Person.friends)).all()
+
+* **query.join() greatly enhanced.** - You can now specify
+ the target and ON clause for a join in multiple ways. A
+ target class alone can be provided where SQLA will attempt
+ to form a join to it via foreign key in the same way as
+ ``table.join(someothertable)``. A target and an explicit
+ ON condition can be provided, where the ON condition can
+ be a ``relation()`` name, an actual class descriptor, or a
+ SQL expression. Or the old way of just a ``relation()``
+ name or class descriptor works too. See the ORM tutorial
+ which has several examples.
+
+* **Declarative is recommended for applications which don't
+ require (and don't prefer) abstraction between tables and
+ mappers** - The [/docs/05/reference/ext/declarative.html
+ Declarative] module, which is used to combine the
+ expression of ``Table``, ``mapper()``, and user defined
+ class objects together, is highly recommended as it
+ simplifies application configuration, ensures the "one
+ mapper per class" pattern, and allows the full range of
+ configuration available to distinct ``mapper()`` calls.
+ Separate ``mapper()`` and ``Table`` usage is now referred
+ to as "classical SQLAlchemy usage" and of course is freely
+ mixable with declarative.
+
+* **The .c. attribute has been removed** from classes (i.e.
+ ``MyClass.c.somecolumn``). As is the case in 0.4, class-
+ level properties are usable as query elements, i.e.
+ ``Class.c.propname`` is now superseded by
+ ``Class.propname``, and the ``c`` attribute continues to
+ remain on ``Table`` objects where they indicate the
+ namespace of ``Column`` objects present on the table.
+
+ To get at the Table for a mapped class (if you didn't keep
+ it around already):
+
+ ::
+
+ table = class_mapper(someclass).mapped_table
+
+ Iterate through columns:
+
+ ::
+
+ for col in table.c:
+ print col
+
+ Work with a specific column:
+
+ ::
+
+ table.c.somecolumn
+
+ The class-bound descriptors support the full set of Column
+ operators as well as the documented relation-oriented
+ operators like ``has()``, ``any()``, ``contains()``, etc.
+
+ The reason for the hard removal of ``.c.`` is that in 0.5,
+ class-bound descriptors carry potentially different
+ meaning, as well as information regarding class mappings,
+ versus plain ``Column`` objects - and there are use cases
+ where you'd specifically want to use one or the other.
+ Generally, using class-bound descriptors invokes a set of
+ mapping/polymorphic aware translations, and using table-
+ bound columns does not. In 0.4, these translations were
+ applied across the board to all expressions, but 0.5
+ differentiates completely between columns and mapped
+ descriptors, only applying translations to the latter. So
+ in many cases, particularly when dealing with joined table
+ inheritance configurations as well as when using
+ ``query(<columns>)``, ``Class.propname`` and
+ ``table.c.colname`` are not interchangeable.
+
+ For example, ``session.query(users.c.id, users.c.name)``
+ is different versus ``session.query(User.id, User.name)``;
+ in the latter case, the ``Query`` is aware of the mapper
+ in use and further mapper-specific operations like
+ ``query.join(<propname>)``, ``query.with_parent()`` etc.
+ may be used, but in the former case cannot. Additionally,
+ in polymorphic inheritance scenarios, the class-bound
+ descriptors refer to the columns present in the
+ polymorphic selectable in use, not necessarily the table
+ column which directly corresponds to the descriptor. For
+ example, a set of classes related by joined-table
+ inheritance to the ``person`` table along the
+ ``person_id`` column of each table will all have their
+ ``Class.person_id`` attribute mapped to the ``person_id``
+ column in ``person``, and not their subclass table.
+ Version 0.4 would map this behavior onto table-bound
+ ``Column`` objects automatically. In 0.5, this automatic
+ conversion has been removed, so that you in fact *can* use
+ table-bound columns as a means to override the
+ translations which occur with polymorphic querying; this
+ allows ``Query`` to be able to create optimized selects
+ among joined-table or concrete-table inheritance setups,
+ as well as portable subqueries, etc.
+
+* **Session Now Synchronizes Automatically with
+ Transactions.** Session now synchronizes against the
+ transaction automatically by default, including autoflush
+ and autoexpire. A transaction is present at all times
+ unless disabled using the ``autocommit`` option. When all
+ three flags are set to their default, the Session recovers
+ gracefully after rollbacks and it's very difficult to get
+ stale data into the session. See the new Session
+ documentation for details.
+
+* **Implicit Order By Is Removed**. This will impact ORM
+ users who rely upon SA's "implicit ordering" behavior,
+ which states that all Query objects which don't have an
+ ``order_by()`` will ORDER BY the "id" or "oid" column of
+ the primary mapped table, and all lazy/eagerly loaded
+ collections apply a similar ordering. In 0.5, automatic
+ ordering must be explicitly configured on ``mapper()`` and
+ ``relation()`` objects (if desired), or otherwise when
+ using ``Query``.
+
+ To convert an 0.4 mapping to 0.5, such that its ordering
+ behavior will be extremely similar to 0.4 or previous, use
+ the ``order_by`` setting on ``mapper()`` and
+ ``relation()``:
+
+ ::
+
+ mapper(User, users, properties={
+ 'addresses':relation(Address, order_by=addresses.c.id)
+ }, order_by=users.c.id)
+
+ To set ordering on a backref, use the ``backref()``
+ function:
+
+ ::
+
+ 'keywords':relation(Keyword, secondary=item_keywords,
+ order_by=keywords.c.name, backref=backref('items', order_by=items.c.id))
+
+ Using declarative ? To help with the new ``order_by``
+ requirement, ``order_by`` and friends can now be set using
+ strings which are evaluated in Python later on (this works
+ **only** with declarative, not plain mappers):
+
+ ::
+
+ class MyClass(MyDeclarativeBase):
+ ...
+ 'addresses':relation("Address", order_by="Address.id")
+
+ It's generally a good idea to set ``order_by`` on
+ ``relation()s`` which load list-based collections of
+ items, since that ordering cannot otherwise be affected.
+ Other than that, the best practice is to use
+ ``Query.order_by()`` to control ordering of the primary
+ entities being loaded.
+
+* **Session is now
+ autoflush=True/autoexpire=True/autocommit=False.** - To
+ set it up, just call ``sessionmaker()`` with no arguments.
+ The name ``transactional=True`` is now
+ ``autocommit=False``. Flushes occur upon each query
+ issued (disable with ``autoflush=False``), within each
+ ``commit()`` (as always), and before each
+ ``begin_nested()`` (so rolling back to the SAVEPOINT is
+ meaningful). All objects are expired after each
+ ``commit()`` and after each ``rollback()``. After
+ rollback, pending objects are expunged, deleted objects
+ move back to persistent. These defaults work together
+ very nicely and there's really no more need for old
+ techniques like ``clear()`` (which is renamed to
+ ``expunge_all()`` as well).
+
+ P.S.: sessions are now reusable after a ``rollback()``.
+ Scalar and collection attribute changes, adds and deletes
+ are all rolled back.
+
+* **session.add() replaces session.save(), session.update(),
+ session.save_or_update().** - the
+ ``session.add(someitem)`` and ``session.add_all([list of
+ items])`` methods replace ``save()``, ``update()``, and
+ ``save_or_update()``. Those methods will remain
+ deprecated throughout 0.5.
+
+* **backref configuration made less verbose.** - The
+ ``backref()`` function now uses the ``primaryjoin`` and
+ ``secondaryjoin`` arguments of the forwards-facing
+ ``relation()`` when they are not explicitly stated. It's
+ no longer necessary to specify
+ ``primaryjoin``/``secondaryjoin`` in both directions
+ separately.
+
+* **Simplified polymorphic options.** - The ORM's
+ "polymorphic load" behavior has been simplified. In 0.4,
+ mapper() had an argument called ``polymorphic_fetch``
+ which could be configured as ``select`` or ``deferred``.
+ This option is removed; the mapper will now just defer any
+ columns which were not present in the SELECT statement.
+ The actual SELECT statement used is controlled by the
+ ``with_polymorphic`` mapper argument (which is also in 0.4
+ and replaces ``select_table``), as well as the
+ ``with_polymorphic()`` method on ``Query`` (also in 0.4).
+
+ An improvement to the deferred loading of inheriting
+ classes is that the mapper now produces the "optimized"
+ version of the SELECT statement in all cases; that is, if
+ class B inherits from A, and several attributes only
+ present on class B have been expired, the refresh
+ operation will only include B's table in the SELECT
+ statement and will not JOIN to A.
+
+* The ``execute()`` method on ``Session`` converts plain
+ strings into ``text()`` constructs, so that bind
+ parameters may all be specified as ":bindname" without
+ needing to call ``text()`` explicitly. If "raw" SQL is
+ desired here, use ``session.connection().execute("raw
+ text")``.
+
+* ``session.Query().iterate_instances()`` has been renamed
+ to just ``instances()``. The old ``instances()`` method
+ returning a list instead of an iterator no longer exists.
+ If you were relying on that behavior, you should use
+ ``list(your_query.instances())``.
+
+Extending the ORM
+=================
+
+In 0.5 we're moving forward with more ways to modify and
+extend the ORM. Heres a summary:
+
+* **MapperExtension.** - This is the classic extension
+ class, which remains. Methods which should rarely be
+ needed are ``create_instance()`` and
+ ``populate_instance()``. To control the initialization of
+ an object when it's loaded from the database, use the
+ ``reconstruct_instance()`` method, or more easily the
+ ``@reconstructor`` decorator described in the
+ documentation.
+
+* **SessionExtension.** - This is an easy to use extension
+ class for session events. In particular, it provides
+ ``before_flush()``, ``after_flush()`` and
+ ``after_flush_postexec()`` methods. It's usage is
+ recommended over ``MapperExtension.before_XXX`` in many
+ cases since within ``before_flush()`` you can modify the
+ flush plan of the session freely, something which cannot
+ be done from within ``MapperExtension``.
+
+* **AttributeExtension.** - This class is now part of the
+ public API, and allows the interception of userland events
+ on attributes, including attribute set and delete
+ operations, and collection appends and removes. It also
+ allows the value to be set or appended to be modified.
+ The ``@validates`` decorator, described in the
+ documentation, provides a quick way to mark any mapped
+ attributes as being "validated" by a particular class
+ method.
+
+* **Attribute Instrumentation Customization.** - An API is
+ provided for ambitious efforts to entirely replace
+ SQLAlchemy's attribute instrumentation, or just to augment
+ it in some cases. This API was produced for the purposes
+ of the Trellis toolkit, but is available as a public API.
+ Some examples are provided in the distribution in the
+ ``/examples/custom_attributes`` directory.
+
+Schema/Types
+============
+
+* **String with no length no longer generates TEXT, it
+ generates VARCHAR** - The ``String`` type no longer
+ magically converts into a ``Text`` type when specified
+ with no length. This only has an effect when CREATE TABLE
+ is issued, as it will issue ``VARCHAR`` with no length
+ parameter, which is not valid on many (but not all)
+ databases. To create a TEXT (or CLOB, i.e. unbounded
+ string) column, use the ``Text`` type.
+
+* **PickleType() with mutable=True requires an __eq__()
+ method** - The ``PickleType`` type needs to compare values
+ when mutable=True. The method of comparing
+ ``pickle.dumps()`` is inefficient and unreliable. If an
+ incoming object does not implement ``__eq__()`` and is
+ also not ``None``, the ``dumps()`` comparison is used but
+ a warning is raised. For types which implement
+ ``__eq__()`` which includes all dictionaries, lists, etc.,
+ comparison will use ``==`` and is now reliable by default.
+
+* **convert_bind_param() and convert_result_value() methods
+ of TypeEngine/TypeDecorator are removed.** - The O'Reilly
+ book unfortunately documented these methods even though
+ they were deprecated post 0.3. For a user-defined type
+ which subclasses ``TypeEngine``, the ``bind_processor()``
+ and ``result_processor()`` methods should be used for
+ bind/result processing. Any user defined type, whether
+ extending ``TypeEngine`` or ``TypeDecorator``, which uses
+ the old 0.3 style can be easily adapted to the new style
+ using the following adapter:
+
+ ::
+
+ class AdaptOldConvertMethods(object):
+ """A mixin which adapts 0.3-style convert_bind_param and
+ convert_result_value methods
+
+ """
+ def bind_processor(self, dialect):
+ def convert(value):
+ return self.convert_bind_param(value, dialect)
+ return convert
+
+ def result_processor(self, dialect):
+ def convert(value):
+ return self.convert_result_value(value, dialect)
+ return convert
+
+ def convert_result_value(self, value, dialect):
+ return value
+
+ def convert_bind_param(self, value, dialect):
+ return value
+
+ To use the above mixin:
+
+ ::
+
+ class MyType(AdaptOldConvertMethods, TypeEngine):
+ # ...
+
+* The ``quote`` flag on ``Column`` and ``Table`` as well as
+ the ``quote_schema`` flag on ``Table`` now control quoting
+ both positively and negatively. The default is ``None``,
+ meaning let regular quoting rules take effect. When
+ ``True``, quoting is forced on. When ``False``, quoting
+ is forced off.
+
+* Column ``DEFAULT`` value DDL can now be more conveniently
+ specified with ``Column(..., server_default='val')``,
+ deprecating ``Column(..., PassiveDefault('val'))``.
+ ``default=`` is now exclusively for Python-initiated
+ default values, and can coexist with server_default. A
+ new ``server_default=FetchedValue()`` replaces the
+ ``PassiveDefault('')`` idiom for marking columns as
+ subject to influence from external triggers and has no DDL
+ side effects.
+
+* SQLite's ``DateTime``, ``Time`` and ``Date`` types now
+ **only accept datetime objects, not strings** as bind
+ parameter input. If you'd like to create your own
+ "hybrid" type which accepts strings and returns results as
+ date objects (from whatever format you'd like), create a
+ ``TypeDecorator`` that builds on ``String``. If you only
+ want string-based dates, just use ``String``.
+
+* Additionally, the ``DateTime`` and ``Time`` types, when
+ used with SQLite, now represent the "microseconds" field
+ of the Python ``datetime.datetime`` object in the same
+ manner as ``str(datetime)`` - as fractional seconds, not a
+ count of microseconds. That is:
+
+ ::
+
+ dt = datetime.datetime(2008, 6, 27, 12, 0, 0, 125) # 125 usec
+
+ # old way
+ '2008-06-27 12:00:00.125'
+
+ # new way
+ '2008-06-27 12:00:00.000125'
+
+ So if an existing SQLite file-based database intends to be
+ used across 0.4 and 0.5, you either have to upgrade the
+ datetime columns to store the new format (NOTE: please
+ test this, I'm pretty sure its correct):
+
+ ::
+
+ UPDATE mytable SET somedatecol =
+ substr(somedatecol, 0, 19) || '.' || substr((substr(somedatecol, 21, -1) / 1000000), 3, -1);
+
+ or, enable "legacy" mode as follows:
+
+ ::
+
+ from sqlalchemy.databases.sqlite import DateTimeMixin
+ DateTimeMixin.__legacy_microseconds__ = True
+
+Connection Pool no longer threadlocal by default
+================================================
+
+0.4 has an unfortunate default setting of
+"pool_threadlocal=True", leading to surprise behavior when,
+for example, using multiple Sessions within a single thread.
+This flag is now off in 0.5. To re-enable 0.4's behavior,
+specify ``pool_threadlocal=True`` to ``create_engine()``, or
+alternatively use the "threadlocal" strategy via
+``strategy="threadlocal"``.
+
+\*args Accepted, \*args No Longer Accepted
+==========================================
+
+The policy with ``method(\*args)`` vs. ``method([args])``
+is, if the method accepts a variable-length set of items
+which represent a fixed structure, it takes ``\*args``. If
+the method accepts a variable-length set of items that are
+data-driven, it takes ``[args]``.
+
+* The various Query.options() functions ``eagerload()``,
+ ``eagerload_all()``, ``lazyload()``, ``contains_eager()``,
+ ``defer()``, ``undefer()`` all accept variable-length
+ ``\*keys`` as their argument now, which allows a path to
+ be formulated using descriptors, ie.:
+
+ ::
+
+ query.options(eagerload_all(User.orders, Order.items, Item.keywords))
+
+ A single array argument is still accepted for backwards
+ compatibility.
+
+* Similarly, the ``Query.join()`` and ``Query.outerjoin()``
+ methods accept a variable length \*args, with a single
+ array accepted for backwards compatibility:
+
+ ::
+
+ query.join('orders', 'items')
+ query.join(User.orders, Order.items)
+
+* the ``in_()`` method on columns and similar only accepts a
+ list argument now. It no longer accepts ``\*args``.
+
+Removed
+=======
+
+* **entity_name** - This feature was always problematic and
+ rarely used. 0.5's more deeply fleshed out use cases
+ revealed further issues with ``entity_name`` which led to
+ its removal. If different mappings are required for a
+ single class, break the class into separate subclasses and
+ map them separately. An example of this is at
+ [wiki:UsageRecipes/EntityName]. More information
+ regarding rationale is described at http://groups.google.c
+ om/group/sqlalchemy/browse_thread/thread/9e23a0641a88b96d?
+ hl=en .
+
+* **get()/load() cleanup**
+
+
+ The ``load()`` method has been removed. It's
+ functionality was kind of arbitrary and basically copied
+ from Hibernate, where it's also not a particularly
+ meaningful method.
+
+ To get equivalent functionality:
+
+ ::
+
+ x = session.query(SomeClass).populate_existing().get(7)
+
+ ``Session.get(cls, id)`` and ``Session.load(cls, id)``
+ have been removed. ``Session.get()`` is redundant vs.
+ ``session.query(cls).get(id)``.
+
+ ``MapperExtension.get()`` is also removed (as is
+ ``MapperExtension.load()``). To override the
+ functionality of ``Query.get()``, use a subclass:
+
+ ::
+
+ class MyQuery(Query):
+ def get(self, ident):
+ # ...
+
+ session = sessionmaker(query_cls=MyQuery)()
+
+ ad1 = session.query(Address).get(1)
+
+* ``sqlalchemy.orm.relation()``
+
+
+ The following deprecated keyword arguments have been
+ removed:
+
+ foreignkey, association, private, attributeext, is_backref
+
+ In particular, ``attributeext`` is replaced with
+ ``extension`` - the ``AttributeExtension`` class is now in
+ the public API.
+
+* ``session.Query()``
+
+
+ The following deprecated functions have been removed:
+
+ list, scalar, count_by, select_whereclause, get_by,
+ select_by, join_by, selectfirst, selectone, select,
+ execute, select_statement, select_text, join_to, join_via,
+ selectfirst_by, selectone_by, apply_max, apply_min,
+ apply_avg, apply_sum
+
+ Additionally, the ``id`` keyword argument to ``join()``,
+ ``outerjoin()``, ``add_entity()`` and ``add_column()`` has
+ been removed. To target table aliases in ``Query`` to
+ result columns, use the ``aliased`` construct:
+
+ ::
+
+ from sqlalchemy.orm import aliased
+ address_alias = aliased(Address)
+ print session.query(User, address_alias).join((address_alias, User.addresses)).all()
+
+* ``sqlalchemy.orm.Mapper``
+
+
+ * instances()
+
+
+ * get_session() - this method was not very noticeable, but
+ had the effect of associating lazy loads with a
+ particular session even if the parent object was
+ entirely detached, when an extension such as
+ ``scoped_session()`` or the old ``SessionContextExt``
+ was used. It's possible that some applications which
+ relied upon this behavior will no longer work as
+ expected; but the better programming practice here is
+ to always ensure objects are present within sessions if
+ database access from their attributes are required.
+
+* ``mapper(MyClass, mytable)``
+
+
+ Mapped classes no are longer instrumented with a "c" class
+ attribute; e.g. ``MyClass.c``
+
+* ``sqlalchemy.orm.collections``
+
+
+ The _prepare_instrumentation alias for
+ prepare_instrumentation has been removed.
+
+* ``sqlalchemy.orm``
+
+
+ Removed the ``EXT_PASS`` alias of ``EXT_CONTINUE``.
+
+* ``sqlalchemy.engine``
+
+
+ The alias from ``DefaultDialect.preexecute_sequences`` to
+ ``.preexecute_pk_sequences`` has been removed.
+
+ The deprecated engine_descriptors() function has been
+ removed.
+
+* ``sqlalchemy.ext.activemapper``
+
+
+ Module removed.
+
+* ``sqlalchemy.ext.assignmapper``
+
+
+ Module removed.
+
+* ``sqlalchemy.ext.associationproxy``
+
+
+ Pass-through of keyword args on the proxy's
+ ``.append(item, \**kw)`` has been removed and is now
+ simply ``.append(item)``
+
+* ``sqlalchemy.ext.selectresults``,
+ ``sqlalchemy.mods.selectresults``
+
+ Modules removed.
+
+* ``sqlalchemy.ext.declarative``
+
+
+ ``declared_synonym()`` removed.
+
+* ``sqlalchemy.ext.sessioncontext``
+
+
+ Module removed.
+
+* ``sqlalchemy.log``
+
+
+ The ``SADeprecationWarning`` alias to
+ ``sqlalchemy.exc.SADeprecationWarning`` has been removed.
+
+* ``sqlalchemy.exc``
+
+
+ ``exc.AssertionError`` has been removed and usage replaced
+ by the Python built-in of the same name.
+
+* ``sqlalchemy.databases.mysql``
+
+
+ The deprecated ``get_version_info`` dialect method has
+ been removed.
+
+Renamed or Moved
+================
+
+* ``sqlalchemy.exceptions`` is now ``sqlalchemy.exc``
+
+
+ The module may still be imported under the old name until
+ 0.6.
+
+* ``FlushError``, ``ConcurrentModificationError``,
+ ``UnmappedColumnError`` -> sqlalchemy.orm.exc
+
+ These exceptions moved to the orm package. Importing
+ 'sqlalchemy.orm' will install aliases in sqlalchemy.exc
+ for compatibility until 0.6.
+
+* ``sqlalchemy.logging`` -> ``sqlalchemy.log``
+
+
+ This internal module was renamed. No longer needs to be
+ special cased when packaging SA with py2app and similar
+ tools that scan imports.
+
+* ``session.Query().iterate_instances()`` ->
+ ``session.Query().instances()``.
+
+Deprecated
+==========
+
+* ``Session.save()``, ``Session.update()``,
+ ``Session.save_or_update()``
+
+ All three replaced by ``Session.add()``
+
+* ``sqlalchemy.PassiveDefault``
+
+
+ Use ``Column(server_default=...)`` Translates to
+ sqlalchemy.DefaultClause() under the hood.
+
+* ``session.Query().iterate_instances()``. It has been
+ renamed to ``instances()``.
+
--- /dev/null
+==============================
+What's New in SQLAlchemy 0.6 ?
+==============================
+
+.. admonition:: About this Document
+
+ This document describes changes between SQLAlchemy version 0.5,
+ last released January 16, 2010, and SQLAlchemy version 0.6,
+ last released May 5, 2012.
+
+ Document date: June 6, 2010
+
+This guide documents API changes which affect users
+migrating their applications from the 0.5 series of
+SQLAlchemy to 0.6. Note that SQLAlchemy 0.6 removes some
+behaviors which were deprecated throughout the span of the
+0.5 series, and also deprecates more behaviors specific to
+0.5.
+
+Platform Support
+================
+
+* cPython versions 2.4 and upwards throughout the 2.xx
+ series
+
+* Jython 2.5.1 - using the zxJDBC DBAPI included with
+ Jython.
+
+* cPython 3.x - see [source:sqlalchemy/trunk/README.py3k]
+ for information on how to build for python3.
+
+New Dialect System
+==================
+
+Dialect modules are now broken up into distinct
+subcomponents, within the scope of a single database
+backend. Dialect implementations are now in the
+``sqlalchemy.dialects`` package. The
+``sqlalchemy.databases`` package still exists as a
+placeholder to provide some level of backwards compatibility
+for simple imports.
+
+For each supported database, a sub-package exists within
+``sqlalchemy.dialects`` where several files are contained.
+Each package contains a module called ``base.py`` which
+defines the specific SQL dialect used by that database. It
+also contains one or more "driver" modules, each one
+corresponding to a specific DBAPI - these files are named
+corresponding to the DBAPI itself, such as ``pysqlite``,
+``cx_oracle``, or ``pyodbc``. The classes used by
+SQLAlchemy dialects are first declared in the ``base.py``
+module, defining all behavioral characteristics defined by
+the database. These include capability mappings, such as
+"supports sequences", "supports returning", etc., type
+definitions, and SQL compilation rules. Each "driver"
+module in turn provides subclasses of those classes as
+needed which override the default behavior to accommodate
+the additional features, behaviors, and quirks of that
+DBAPI. For DBAPIs that support multiple backends (pyodbc,
+zxJDBC, mxODBC), the dialect module will use mixins from the
+``sqlalchemy.connectors`` package, which provide
+functionality common to that DBAPI across all backends, most
+typically dealing with connect arguments. This means that
+connecting using pyodbc, zxJDBC or mxODBC (when implemented)
+is extremely consistent across supported backends.
+
+The URL format used by ``create_engine()`` has been enhanced
+to handle any number of DBAPIs for a particular backend,
+using a scheme that is inspired by that of JDBC. The
+previous format still works, and will select a "default"
+DBAPI implementation, such as the Postgresql URL below that
+will use psycopg2:
+
+::
+
+ create_engine('postgresql://scott:tiger@localhost/test')
+
+However to specify a specific DBAPI backend such as pg8000,
+add it to the "protocol" section of the URL using a plus
+sign "+":
+
+::
+
+ create_engine('postgresql+pg8000://scott:tiger@localhost/test')
+
+Important Dialect Links:
+
+* Documentation on connect arguments:
+ http://www.sqlalchemy.org/docs/06/dbengine.html#create-
+ engine-url-arguments.
+
+* Reference documentation for individual dialects: http://ww
+ w.sqlalchemy.org/docs/06/reference/dialects/index.html
+
+* The tips and tricks at DatabaseNotes.
+
+
+Other notes regarding dialects:
+
+* the type system has been changed dramatically in
+ SQLAlchemy 0.6. This has an impact on all dialects
+ regarding naming conventions, behaviors, and
+ implementations. See the section on "Types" below.
+
+* the ``ResultProxy`` object now offers a 2x speed
+ improvement in some cases thanks to some refactorings.
+
+* the ``RowProxy``, i.e. individual result row object, is
+ now directly pickleable.
+
+* the setuptools entrypoint used to locate external dialects
+ is now called ``sqlalchemy.dialects``. An external
+ dialect written against 0.4 or 0.5 will need to be
+ modified to work with 0.6 in any case so this change does
+ not add any additional difficulties.
+
+* dialects now receive an initialize() event on initial
+ connection to determine connection properties.
+
+* Functions and operators generated by the compiler now use
+ (almost) regular dispatch functions of the form
+ "visit_<opname>" and "visit_<funcname>_fn" to provide
+ customed processing. This replaces the need to copy the
+ "functions" and "operators" dictionaries in compiler
+ subclasses with straightforward visitor methods, and also
+ allows compiler subclasses complete control over
+ rendering, as the full _Function or _BinaryExpression
+ object is passed in.
+
+Dialect Imports
+---------------
+
+The import structure of dialects has changed. Each dialect
+now exports its base "dialect" class as well as the full set
+of SQL types supported on that dialect via
+``sqlalchemy.dialects.<name>``. For example, to import a
+set of PG types:
+
+::
+
+ from sqlalchemy.dialects.postgresql import INTEGER, BIGINT, SMALLINT,\
+ VARCHAR, MACADDR, DATE, BYTEA
+
+Above, ``INTEGER`` is actually the plain ``INTEGER`` type
+from ``sqlalchemy.types``, but the PG dialect makes it
+available in the same way as those types which are specific
+to PG, such as ``BYTEA`` and ``MACADDR``.
+
+Expression Language Changes
+===========================
+
+An Important Expression Language Gotcha
+---------------------------------------
+
+There's one quite significant behavioral change to the
+expression language which may affect some applications.
+The boolean value of Python boolean expressions, i.e.
+``==``, ``!=``, and similar, now evaluates accurately with
+regards to the two clause objects being compared.
+
+As we know, comparing a ``ClauseElement`` to any other
+object returns another ``ClauseElement``:
+
+::
+
+ >>> from sqlalchemy.sql import column
+ >>> column('foo') == 5
+ <sqlalchemy.sql.expression._BinaryExpression object at 0x1252490>
+
+This so that Python expressions produce SQL expressions when
+converted to strings:
+
+::
+
+ >>> str(column('foo') == 5)
+ 'foo = :foo_1'
+
+But what happens if we say this?
+
+::
+
+ >>> if column('foo') == 5:
+ ... print "yes"
+ ...
+
+In previous versions of SQLAlchemy, the returned
+``_BinaryExpression`` was a plain Python object which
+evaluated to ``True``. Now it evaluates to whether or not
+the actual ``ClauseElement`` should have the same hash value
+as to that being compared. Meaning:
+
+::
+
+ >>> bool(column('foo') == 5)
+ False
+ >>> bool(column('foo') == column('foo'))
+ False
+ >>> c = column('foo')
+ >>> bool(c == c)
+ True
+ >>>
+
+That means code such as the following:
+
+::
+
+ if expression:
+ print "the expression is:", expression
+
+Would not evaluate if ``expression`` was a binary clause.
+Since the above pattern should never be used, the base
+``ClauseElement`` now raises an exception if called in a
+boolean context:
+
+::
+
+ >>> bool(c)
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ ...
+ raise TypeError("Boolean value of this clause is not defined")
+ TypeError: Boolean value of this clause is not defined
+
+Code that wants to check for the presence of a
+``ClauseElement`` expression should instead say:
+
+::
+
+ if expression is not None:
+ print "the expression is:", expression
+
+Keep in mind, **this applies to Table and Column objects
+too**.
+
+The rationale for the change is twofold:
+
+* Comparisons of the form ``if c1 == c2: <do something>``
+ can actually be written now
+
+* Support for correct hashing of ``ClauseElement`` objects
+ now works on alternate platforms, namely Jython. Up until
+ this point SQLAlchemy relied heavily on the specific
+ behavior of cPython in this regard (and still had
+ occasional problems with it).
+
+Stricter "executemany" Behavior
+-------------------------------
+
+An "executemany" in SQLAlchemy corresponds to a call to
+``execute()``, passing along a collection of bind parameter
+sets:
+
+::
+
+ connection.execute(table.insert(), {'data':'row1'}, {'data':'row2'}, {'data':'row3'})
+
+When the ``Connection`` object sends off the given
+``insert()`` construct for compilation, it passes to the
+compiler the keynames present in the first set of binds
+passed along to determine the construction of the
+statement's VALUES clause. Users familiar with this
+construct will know that additional keys present in the
+remaining dictionaries don't have any impact. What's
+different now is that all subsequent dictionaries need to
+include at least *every* key that is present in the first
+dictionary. This means that a call like this no longer
+works:
+
+::
+
+ connection.execute(table.insert(),
+ {'timestamp':today, 'data':'row1'},
+ {'timestamp':today, 'data':'row2'},
+ {'data':'row3'})
+
+Because the third row does not specify the 'timestamp'
+column. Previous versions of SQLAlchemy would simply insert
+NULL for these missing columns. However, if the
+``timestamp`` column in the above example contained a
+Python-side default value or function, it would *not* be
+used. This because the "executemany" operation is optimized
+for maximum performance across huge numbers of parameter
+sets, and does not attempt to evaluate Python-side defaults
+for those missing keys. Because defaults are often
+implemented either as SQL expressions which are embedded
+inline with the INSERT statement, or are server side
+expressions which again are triggered based on the structure
+of the INSERT string, which by definition cannot fire off
+conditionally based on each parameter set, it would be
+inconsistent for Python side defaults to behave differently
+vs. SQL/server side defaults. (SQL expression based
+defaults are embedded inline as of the 0.5 series, again to
+minimize the impact of huge numbers of parameter sets).
+
+SQLAlchemy 0.6 therefore establishes predictable consistency
+by forbidding any subsequent parameter sets from leaving any
+fields blank. That way, there's no more silent failure of
+Python side default values and functions, which additionally
+are allowed to remain consistent in their behavior versus
+SQL and server side defaults.
+
+UNION and other "compound" constructs parenthesize consistently
+---------------------------------------------------------------
+
+A rule that was designed to help SQLite has been removed,
+that of the first compound element within another compound
+(such as, a ``union()`` inside of an ``except_()``) wouldn't
+be parenthesized. This is inconsistent and produces the
+wrong results on Postgresql, which has precedence rules
+regarding INTERSECTION, and its generally a surprise. When
+using complex composites with SQLite, you now need to turn
+the first element into a subquery (which is also compatible
+on PG). A new example is in the SQL expression tutorial at
+the end of
+[http://www.sqlalchemy.org/docs/06/sqlexpression.html
+#unions-and-other-set-operations]. See :ticket:`1665` and
+r6690 for more background.
+
+C Extensions for Result Fetching
+================================
+
+The ``ResultProxy`` and related elements, including most
+common "row processing" functions such as unicode
+conversion, numerical/boolean conversions and date parsing,
+have been re-implemented as optional C extensions for the
+purposes of performance. This represents the beginning of
+SQLAlchemy's path to the "dark side" where we hope to
+continue improving performance by reimplementing critical
+sections in C. The extensions can be built by specifying
+``--with-cextensions``, i.e. ``python setup.py --with-
+cextensions install``.
+
+The extensions have the most dramatic impact on result
+fetching using direct ``ResultProxy`` access, i.e. that
+which is returned by ``engine.execute()``,
+``connection.execute()``, or ``session.execute()``. Within
+results returned by an ORM ``Query`` object, result fetching
+is not as high a percentage of overhead, so ORM performance
+improves more modestly, and mostly in the realm of fetching
+large result sets. The performance improvements highly
+depend on the dbapi in use and on the syntax used to access
+the columns of each row (eg ``row['name']`` is much faster
+than ``row.name``). The current extensions have no impact
+on the speed of inserts/updates/deletes, nor do they improve
+the latency of SQL execution, that is, an application that
+spends most of its time executing many statements with very
+small result sets will not see much improvement.
+
+Performance has been improved in 0.6 versus 0.5 regardless
+of the extensions. A quick overview of what connecting and
+fetching 50,000 rows looks like with SQLite, using mostly
+direct SQLite access, a ``ResultProxy``, and a simple mapped
+ORM object:
+
+::
+
+ sqlite select/native: 0.260s
+
+ 0.6 / C extension
+
+ sqlalchemy.sql select: 0.360s
+ sqlalchemy.orm fetch: 2.500s
+
+ 0.6 / Pure Python
+
+ sqlalchemy.sql select: 0.600s
+ sqlalchemy.orm fetch: 3.000s
+
+ 0.5 / Pure Python
+
+ sqlalchemy.sql select: 0.790s
+ sqlalchemy.orm fetch: 4.030s
+
+Above, the ORM fetches the rows 33% faster than 0.5 due to
+in-python performance enhancements. With the C extensions
+we get another 20%. However, ``ResultProxy`` fetches
+improve by 67% with the C extension versus not. Other
+tests report as much as a 200% speed improvement for some
+scenarios, such as those where lots of string conversions
+are occurring.
+
+New Schema Capabilities
+=======================
+
+The ``sqlalchemy.schema`` package has received some long-
+needed attention. The most visible change is the newly
+expanded DDL system. In SQLAlchemy, it was possible since
+version 0.5 to create custom DDL strings and associate them
+with tables or metadata objects:
+
+::
+
+ from sqlalchemy.schema import DDL
+
+ DDL('CREATE TRIGGER users_trigger ...').execute_at('after-create', metadata)
+
+Now the full suite of DDL constructs are available under the
+same system, including those for CREATE TABLE, ADD
+CONSTRAINT, etc.:
+
+::
+
+ from sqlalchemy.schema import Constraint, AddConstraint
+
+ AddContraint(CheckConstraint("value > 5")).execute_at('after-create', mytable)
+
+Additionally, all the DDL objects are now regular
+``ClauseElement`` objects just like any other SQLAlchemy
+expression object:
+
+::
+
+ from sqlalchemy.schema import CreateTable
+
+ create = CreateTable(mytable)
+
+ # dumps the CREATE TABLE as a string
+ print create
+
+ # executes the CREATE TABLE statement
+ engine.execute(create)
+
+and using the ``sqlalchemy.ext.compiler`` extension you can
+make your own:
+
+::
+
+ from sqlalchemy.schema import DDLElement
+ from sqlalchemy.ext.compiler import compiles
+
+ class AlterColumn(DDLElement):
+
+ def __init__(self, column, cmd):
+ self.column = column
+ self.cmd = cmd
+
+ @compiles(AlterColumn)
+ def visit_alter_column(element, compiler, **kw):
+ return "ALTER TABLE %s ALTER COLUMN %s %s ..." % (
+ element.column.table.name,
+ element.column.name,
+ element.cmd
+ )
+
+ engine.execute(AlterColumn(table.c.mycolumn, "SET DEFAULT 'test'"))
+
+Deprecated/Removed Schema Elements
+----------------------------------
+
+The schema package has also been greatly streamlined. Many
+options and methods which were deprecated throughout 0.5
+have been removed. Other little known accessors and methods
+have also been removed.
+
+* the "owner" keyword argument is removed from ``Table``.
+ Use "schema" to represent any namespaces to be prepended
+ to the table name.
+
+* deprecated ``MetaData.connect()`` and
+ ``ThreadLocalMetaData.connect()`` have been removed - send
+ the "bind" attribute to bind a metadata.
+
+* deprecated metadata.table_iterator() method removed (use
+ sorted_tables)
+
+* the "metadata" argument is removed from
+ ``DefaultGenerator`` and subclasses, but remains locally
+ present on ``Sequence``, which is a standalone construct
+ in DDL.
+
+* deprecated ``PassiveDefault`` - use ``DefaultClause``.
+
+
+* Removed public mutability from ``Index`` and
+ ``Constraint`` objects:
+
+ * ``ForeignKeyConstraint.append_element()``
+
+
+ * ``Index.append_column()``
+
+
+ * ``UniqueConstraint.append_column()``
+
+
+ * ``PrimaryKeyConstraint.add()``
+
+
+ * ``PrimaryKeyConstraint.remove()``
+
+
+These should be constructed declaratively (i.e. in one
+construction).
+
+* Other removed things:
+
+
+ * ``Table.key`` (no idea what this was for)
+
+
+ * ``Column.bind`` (get via column.table.bind)
+
+
+ * ``Column.metadata`` (get via column.table.metadata)
+
+
+ * ``Column.sequence`` (use column.default)
+
+
+Other Behavioral Changes
+------------------------
+
+* ``UniqueConstraint``, ``Index``, ``PrimaryKeyConstraint``
+ all accept lists of column names or column objects as
+ arguments.
+
+* The ``use_alter`` flag on ``ForeignKey`` is now a shortcut
+ option for operations that can be hand-constructed using
+ the ``DDL()`` event system. A side effect of this refactor
+ is that ``ForeignKeyConstraint`` objects with
+ ``use_alter=True`` will *not* be emitted on SQLite, which
+ does not support ALTER for foreign keys. This has no
+ effect on SQLite's behavior since SQLite does not actually
+ honor FOREIGN KEY constraints.
+
+* ``Table.primary_key`` is not assignable - use
+ ``table.append_constraint(PrimaryKeyConstraint(...))``
+
+* A ``Column`` definition with a ``ForeignKey`` and no type,
+ e.g. ``Column(name, ForeignKey(sometable.c.somecol))``
+ used to get the type of the referenced column. Now support
+ for that automatic type inference is partial and may not
+ work in all cases.
+
+Logging opened up
+=================
+
+At the expense of a few extra method calls here and there,
+you can set log levels for INFO and DEBUG after an engine,
+pool, or mapper has been created, and logging will commence.
+The ``isEnabledFor(INFO)`` method is now called
+per-``Connection`` and ``isEnabledFor(DEBUG)``
+per-``ResultProxy`` if already enabled on the parent
+connection. Pool logging sends to ``log.info()`` and
+``log.debug()`` with no check - note that pool
+checkout/checkin is typically once per transaction.
+
+Reflection/Inspector API
+========================
+
+The reflection system, which allows reflection of table
+columns via ``Table('sometable', metadata, autoload=True)``
+has been opened up into its own fine-grained API, which
+allows direct inspection of database elements such as
+tables, columns, constraints, indexes, and more. This API
+expresses return values as simple lists of strings,
+dictionaries, and ``TypeEngine`` objects. The internals of
+``autoload=True`` now build upon this system such that the
+translation of raw database information into
+``sqlalchemy.schema`` constructs is centralized and the
+contract of individual dialects greatly simplified, vastly
+reducing bugs and inconsistencies across different backends.
+
+To use an inspector:
+
+::
+
+ from sqlalchemy.engine.reflection import Inspector
+ insp = Inspector.from_engine(my_engine)
+
+ print insp.get_schema_names()
+
+the ``from_engine()`` method will in some cases provide a
+backend-specific inspector with additional capabilities,
+such as that of Postgresql which provides a
+``get_table_oid()`` method:
+
+::
+
+
+ my_engine = create_engine('postgresql://...')
+ pg_insp = Inspector.from_engine(my_engine)
+
+ print pg_insp.get_table_oid('my_table')
+
+RETURNING Support
+=================
+
+The ``insert()``, ``update()`` and ``delete()`` constructs
+now support a ``returning()`` method, which corresponds to
+the SQL RETURNING clause as supported by Postgresql, Oracle,
+MS-SQL, and Firebird. It is not supported for any other
+backend at this time.
+
+Given a list of column expressions in the same manner as
+that of a ``select()`` construct, the values of these
+columns will be returned as a regular result set:
+
+::
+
+
+ result = connection.execute(
+ table.insert().values(data='some data').returning(table.c.id, table.c.timestamp)
+ )
+ row = result.first()
+ print "ID:", row['id'], "Timestamp:", row['timestamp']
+
+The implementation of RETURNING across the four supported
+backends varies wildly, in the case of Oracle requiring an
+intricate usage of OUT parameters which are re-routed into a
+"mock" result set, and in the case of MS-SQL using an
+awkward SQL syntax. The usage of RETURNING is subject to
+limitations:
+
+* it does not work for any "executemany()" style of
+ execution. This is a limitation of all supported DBAPIs.
+
+* Some backends, such as Oracle, only support RETURNING that
+ returns a single row - this includes UPDATE and DELETE
+ statements, meaning the update() or delete() construct
+ must match only a single row, or an error is raised (by
+ Oracle, not SQLAlchemy).
+
+RETURNING is also used automatically by SQLAlchemy, when
+available and when not otherwise specified by an explicit
+``returning()`` call, to fetch the value of newly generated
+primary key values for single-row INSERT statements. This
+means there's no more "SELECT nextval(sequence)" pre-
+execution for insert statements where the primary key value
+is required. Truth be told, implicit RETURNING feature
+does incur more method overhead than the old "select
+nextval()" system, which used a quick and dirty
+cursor.execute() to get at the sequence value, and in the
+case of Oracle requires additional binding of out
+parameters. So if method/protocol overhead is proving to be
+more expensive than additional database round trips, the
+feature can be disabled by specifying
+``implicit_returning=False`` to ``create_engine()``.
+
+Type System Changes
+===================
+
+New Archicture
+--------------
+
+The type system has been completely reworked behind the
+scenes to provide two goals:
+
+* Separate the handling of bind parameters and result row
+ values, typically a DBAPI requirement, from the SQL
+ specification of the type itself, which is a database
+ requirement. This is consistent with the overall dialect
+ refactor that separates database SQL behavior from DBAPI.
+
+* Establish a clear and consistent contract for generating
+ DDL from a ``TypeEngine`` object and for constructing
+ ``TypeEngine`` objects based on column reflection.
+
+Highlights of these changes include:
+
+* The construction of types within dialects has been totally
+ overhauled. Dialects now define publically available types
+ as UPPERCASE names exclusively, and internal
+ implementation types using underscore identifiers (i.e.
+ are private). The system by which types are expressed in
+ SQL and DDL has been moved to the compiler system. This
+ has the effect that there are much fewer type objects
+ within most dialects. A detailed document on this
+ architecture for dialect authors is in [source:/lib/sqlalc
+ hemy/dialects/type_migration_guidelines.txt].
+
+* Reflection of types now returns the exact UPPERCASE type
+ within types.py, or the UPPERCASE type within the dialect
+ itself if the type is not a standard SQL type. This means
+ reflection now returns more accurate information about
+ reflected types.
+
+* User defined types that subclass ``TypeEngine`` and wish
+ to provide ``get_col_spec()`` should now subclass
+ ``UserDefinedType``.
+
+* The ``result_processor()`` method on all type classes now
+ accepts an additional argument ``coltype``. This is the
+ DBAPI type object attached to cursor.description, and
+ should be used when applicable to make better decisions on
+ what kind of result-processing callable should be
+ returned. Ideally result processor functions would never
+ need to use ``isinstance()``, which is an expensive call
+ at this level.
+
+Native Unicode Mode
+-------------------
+
+As more DBAPIs support returning Python unicode objects
+directly, the base dialect now performs a check upon the
+first connection which establishes whether or not the DBAPI
+returns a Python unicode object for a basic select of a
+VARCHAR value. If so, the ``String`` type and all
+subclasses (i.e. ``Text``, ``Unicode``, etc.) will skip the
+"unicode" check/conversion step when result rows are
+received. This offers a dramatic performance increase for
+large result sets. The "unicode mode" currently is known to
+work with:
+
+* sqlite3 / pysqlite
+
+
+* psycopg2 - SQLA 0.6 now uses the "UNICODE" type extension
+ by default on each psycopg2 connection object
+
+* pg8000
+
+
+* cx_oracle (we use an output processor - nice feature !)
+
+
+Other types may choose to disable unicode processing as
+needed, such as the ``NVARCHAR`` type when used with MS-SQL.
+
+In particular, if porting an application based on a DBAPI
+that formerly returned non-unicode strings, the "native
+unicode" mode has a plainly different default behavior -
+columns that are declared as ``String`` or ``VARCHAR`` now
+return unicode by default whereas they would return strings
+before. This can break code which expects non-unicode
+strings. The psycopg2 "native unicode" mode can be
+disabled by passing ``use_native_unicode=False`` to
+``create_engine()``.
+
+A more general solution for string columns that explicitly
+do not want a unicode object is to use a ``TypeDecorator``
+that converts unicode back to utf-8, or whatever is desired:
+
+::
+
+ class UTF8Encoded(TypeDecorator):
+ """Unicode type which coerces to utf-8."""
+
+ impl = sa.VARCHAR
+
+ def process_result_value(self, value, dialect):
+ if isinstance(value, unicode):
+ value = value.encode('utf-8')
+ return value
+
+Note that the ``assert_unicode`` flag is now deprecated.
+SQLAlchemy allows the DBAPI and backend database in use to
+handle Unicode parameters when available, and does not add
+operational overhead by checking the incoming type; modern
+systems like sqlite and Postgresql will raise an encoding
+error on their end if invalid data is passed. In those
+cases where SQLAlchemy does need to coerce a bind parameter
+from Python Unicode to an encoded string, or when the
+Unicode type is used explicitly, a warning is raised if the
+object is a bytestring. This warning can be suppressed or
+converted to an exception using the Python warnings filter
+documented at: http://docs.python.org/library/warnings.html
+
+Generic Enum Type
+-----------------
+
+We now have an ``Enum`` in the ``types`` module. This is a
+string type that is given a collection of "labels" which
+constrain the possible values given to those labels. By
+default, this type generates a ``VARCHAR`` using the size of
+the largest label, and applies a CHECK constraint to the
+table within the CREATE TABLE statement. When using MySQL,
+the type by default uses MySQL's ENUM type, and when using
+Postgresql the type will generate a user defined type using
+``CREATE TYPE <mytype> AS ENUM``. In order to create the
+type using Postgresql, the ``name`` parameter must be
+specified to the constructor. The type also accepts a
+``native_enum=False`` option which will issue the
+VARCHAR/CHECK strategy for all databases. Note that
+Postgresql ENUM types currently don't work with pg8000 or
+zxjdbc.
+
+Reflection Returns Dialect-Specific Types
+-----------------------------------------
+
+Reflection now returns the most specific type possible from
+the database. That is, if you create a table using
+``String``, then reflect it back, the reflected column will
+likely be ``VARCHAR``. For dialects that support a more
+specific form of the type, that's what you'll get. So a
+``Text`` type would come back as ``oracle.CLOB`` on Oracle,
+a ``LargeBinary`` might be an ``mysql.MEDIUMBLOB`` etc. The
+obvious advantage here is that reflection preserves as much
+information possible from what the database had to say.
+
+Some applications that deal heavily in table metadata may
+wish to compare types across reflected tables and/or non-
+reflected tables. There's a semi-private accessor available
+on ``TypeEngine`` called ``_type_affinity`` and an
+associated comparison helper ``_compare_type_affinity``.
+This accessor returns the "generic" ``types`` class which
+the type corresponds to:
+
+::
+
+ >>> String(50)._compare_type_affinity(postgresql.VARCHAR(50))
+ True
+ >>> Integer()._compare_type_affinity(mysql.REAL)
+ False
+
+Miscellaneous API Changes
+-------------------------
+
+The usual "generic" types are still the general system in
+use, i.e. ``String``, ``Float``, ``DateTime``. There's a
+few changes there:
+
+* Types no longer make any guesses as to default parameters.
+ In particular, ``Numeric``, ``Float``, as well as
+ subclasses NUMERIC, FLOAT, DECIMAL don't generate any
+ length or scale unless specified. This also continues to
+ include the controversial ``String`` and ``VARCHAR`` types
+ (although MySQL dialect will pre-emptively raise when
+ asked to render VARCHAR with no length). No defaults are
+ assumed, and if they are used in a CREATE TABLE statement,
+ an error will be raised if the underlying database does
+ not allow non-lengthed versions of these types.
+
+* the ``Binary`` type has been renamed to ``LargeBinary``,
+ for BLOB/BYTEA/similar types. For ``BINARY`` and
+ ``VARBINARY``, those are present directly as
+ ``types.BINARY``, ``types.VARBINARY``, as well as in the
+ MySQL and MS-SQL dialects.
+
+* ``PickleType`` now uses == for comparison of values when
+ mutable=True, unless the "comparator" argument with a
+ comparison function is specified to the type. If you are
+ pickling a custom object you should implement an
+ ``__eq__()`` method so that value-based comparisons are
+ accurate.
+
+* The default "precision" and "scale" arguments of Numeric
+ and Float have been removed and now default to None.
+ NUMERIC and FLOAT will be rendered with no numeric
+ arguments by default unless these values are provided.
+
+* DATE, TIME and DATETIME types on SQLite can now take
+ optional "storage_format" and "regexp" argument.
+ "storage_format" can be used to store those types using a
+ custom string format. "regexp" allows to use a custom
+ regular expression to match string values from the
+ database.
+
+* ``__legacy_microseconds__`` on SQLite ``Time`` and
+ ``DateTime`` types is not supported anymore. You should
+ use the new "storage_format" argument instead.
+
+* ``DateTime`` types on SQLite now use by a default a
+ stricter regular expression to match strings from the
+ database. Use the new "regexp" argument if you are using
+ data stored in a legacy format.
+
+ORM Changes
+===========
+
+Upgrading an ORM application from 0.5 to 0.6 should require
+little to no changes, as the ORM's behavior remains almost
+identical. There are some default argument and name
+changes, and some loading behaviors have been improved.
+
+New Unit of Work
+----------------
+
+The internals for the unit of work, primarily
+``topological.py`` and ``unitofwork.py``, have been
+completely rewritten and are vastly simplified. This
+should have no impact on usage, as all existing behavior
+during flush has been maintained exactly (or at least, as
+far as it is exercised by our testsuite and the handful of
+production environments which have tested it heavily). The
+performance of flush() now uses 20-30% fewer method calls
+and should also use less memory. The intent and flow of the
+source code should now be reasonably easy to follow, and the
+architecture of the flush is fairly open-ended at this
+point, creating room for potential new areas of
+sophistication. The flush process no longer has any
+reliance on recursion so flush plans of arbitrary size and
+complexity can be flushed. Additionally, the mapper's
+"save" process, which issues INSERT and UPDATE statements,
+now caches the "compiled" form of the two statements so that
+callcounts are further dramatically reduced with very large
+flushes.
+
+Any changes in behavior observed with flush versus earlier
+versions of 0.6 or 0.5 should be reported to us ASAP - we'll
+make sure no functionality is lost.
+
+Changes to ``query.update()`` and ``query.delete()``
+----------------------------------------------------
+
+* the 'expire' option on query.update() has been renamed to
+ 'fetch', thus matching that of query.delete()
+
+* ``query.update()`` and ``query.delete()`` both default to
+ 'evaluate' for the synchronize strategy.
+
+* the 'synchronize' strategy for update() and delete()
+ raises an error on failure. There is no implicit fallback
+ onto "fetch". Failure of evaluation is based on the
+ structure of criteria, so success/failure is deterministic
+ based on code structure.
+
+``relation()`` is officially named ``relationship()``
+-----------------------------------------------------
+
+This to solve the long running issue that "relation" means a
+"table or derived table" in relational algebra terms. The
+``relation()`` name, which is less typing, will hang around
+for the foreseeable future so this change should be entirely
+painless.
+
+Subquery eager loading
+----------------------
+
+A new kind of eager loading is added called "subquery"
+loading. This is a load that emits a second SQL query
+immediately after the first which loads full collections for
+all the parents in the first query, joining upwards to the
+parent using INNER JOIN. Subquery loading is used simlarly
+to the current joined-eager loading, using the
+```subqueryload()```` and ````subqueryload_all()```` options
+as well as the ````lazy='subquery'```` setting on
+````relationship()```. The subquery load is usually much
+more efficient for loading many larger collections as it
+uses INNER JOIN unconditionally and also doesn't re-load
+parent rows.
+
+```eagerload()````, ````eagerload_all()```` is now ````joinedload()````, ````joinedload_all()```
+------------------------------------------------------------------------------------------------
+
+To make room for the new subquery load feature, the existing
+```eagerload()````/````eagerload_all()```` options are now
+superceded by ````joinedload()```` and
+````joinedload_all()````. The old names will hang around
+for the foreseeable future just like ````relation()```.
+
+```lazy=False|None|True|'dynamic'```` now accepts ````lazy='noload'|'joined'|'subquery'|'select'|'dynamic'```
+-------------------------------------------------------------------------------------------------------------
+
+Continuing on the theme of loader strategies opened up, the
+standard keywords for the ```lazy```` option on
+````relationship()```` are now ````select```` for lazy
+loading (via a SELECT issued on attribute access),
+````joined```` for joined-eager loading, ````subquery````
+for subquery-eager loading, ````noload```` for no loading
+should occur, and ````dynamic```` for a "dynamic"
+relationship. The old ````True````, ````False````,
+````None``` arguments are still accepted with the identical
+behavior as before.
+
+innerjoin=True on relation, joinedload
+--------------------------------------
+
+Joined-eagerly loaded scalars and collections can now be
+instructed to use INNER JOIN instead of OUTER JOIN. On
+Postgresql this is observed to provide a 300-600% speedup on
+some queries. Set this flag for any many-to-one which is
+on a NOT NULLable foreign key, and similarly for any
+collection where related items are guaranteed to exist.
+
+At mapper level:
+
+::
+
+ mapper(Child, child)
+ mapper(Parent, parent, properties={
+ 'child':relationship(Child, lazy='joined', innerjoin=True)
+ })
+
+At query time level:
+
+::
+
+ session.query(Parent).options(joinedload(Parent.child, innerjoin=True)).all()
+
+The ``innerjoin=True`` flag at the ``relationship()`` level
+will also take effect for any ``joinedload()`` option which
+does not override the value.
+
+Many-to-one Enhancements
+------------------------
+
+* many-to-one relations now fire off a lazyload in fewer
+ cases, including in most cases will not fetch the "old"
+ value when a new one is replaced.
+
+* many-to-one relation to a joined-table subclass now uses
+ get() for a simple load (known as the "use_get"
+ condition), i.e. ``Related``->``Sub(Base)``, without the
+ need to redefine the primaryjoin condition in terms of the
+ base table. [ticket:1186]
+
+* specifying a foreign key with a declarative column, i.e.
+ ``ForeignKey(MyRelatedClass.id)`` doesn't break the
+ "use_get" condition from taking place [ticket:1492]
+
+* relationship(), joinedload(), and joinedload_all() now
+ feature an option called "innerjoin". Specify ``True`` or
+ ``False`` to control whether an eager join is constructed
+ as an INNER or OUTER join. Default is ``False`` as always.
+ The mapper options will override whichever setting is
+ specified on relationship(). Should generally be set for
+ many-to-one, not nullable foreign key relations to allow
+ improved join performance. [ticket:1544]
+
+* the behavior of joined eager loading such that the main
+ query is wrapped in a subquery when LIMIT/OFFSET are
+ present now makes an exception for the case when all eager
+ loads are many-to-one joins. In those cases, the eager
+ joins are against the parent table directly along with the
+ limit/offset without the extra overhead of a subquery,
+ since a many-to-one join does not add rows to the result.
+
+ For example, in 0.5 this query:
+
+ ::
+
+ session.query(Address).options(eagerload(Address.user)).limit(10)
+
+ would produce SQL like:
+
+ ::
+
+ SELECT * FROM
+ (SELECT * FROM addresses LIMIT 10) AS anon_1
+ LEFT OUTER JOIN users AS users_1 ON users_1.id = anon_1.addresses_user_id
+
+ This because the presence of any eager loaders suggests
+ that some or all of them may relate to multi-row
+ collections, which would necessitate wrapping any kind of
+ rowcount-sensitive modifiers like LIMIT inside of a
+ subquery.
+
+ In 0.6, that logic is more sensitive and can detect if all
+ eager loaders represent many-to-ones, in which case the
+ eager joins don't affect the rowcount:
+
+ ::
+
+ SELECT * FROM addresses LEFT OUTER JOIN users AS users_1 ON users_1.id = addresses.user_id LIMIT 10
+
+Mutable Primary Keys with Joined Table Inheritance
+--------------------------------------------------
+
+A joined table inheritance config where the child table has
+a PK that foreign keys to the parent PK can now be updated
+on a CASCADE-capable database like Postgresql.
+``mapper()`` now has an option ``passive_updates=True``
+which indicates this foreign key is updated automatically.
+If on a non-cascading database like SQLite or MySQL/MyISAM,
+set this flag to ``False``. A future feature enhancement
+will try to get this flag to be auto-configuring based on
+dialect/table style in use.
+
+Beaker Caching
+--------------
+
+A promising new example of Beaker integration is in
+``examples/beaker_caching``. This is a straightforward
+recipe which applies a Beaker cache within the result-
+generation engine of ``Query``. Cache parameters are
+provided via ``query.options()``, and allows full control
+over the contents of the cache. SQLAlchemy 0.6 includes
+improvements to the ``Session.merge()`` method to support
+this and similar recipes, as well as to provide
+significantly improved performance in most scenarios.
+
+Other Changes
+-------------
+
+* the "row tuple" object returned by ``Query`` when multiple
+ column/entities are selected is now picklable as well as
+ higher performing.
+
+* ``query.join()`` has been reworked to provide more
+ consistent behavior and more flexibility (includes
+ [ticket:1537])
+
+* ``query.select_from()`` accepts multiple clauses to
+ produce multiple comma separated entries within the FROM
+ clause. Useful when selecting from multiple-homed join()
+ clauses.
+
+* the "dont_load=True" flag on ``Session.merge()`` is
+ deprecated and is now "load=False".
+
+* added "make_transient()" helper function which transforms
+ a persistent/ detached instance into a transient one (i.e.
+ deletes the instance_key and removes from any session.)
+ [ticket:1052]
+
+* the allow_null_pks flag on mapper() is deprecated and has
+ been renamed to allow_partial_pks. It is turned "on" by
+ default. This means that a row which has a non-null value
+ for any of its primary key columns will be considered an
+ identity. The need for this scenario typically only occurs
+ when mapping to an outer join. When set to False, a PK
+ that has NULLs in it will not be considered a primary key
+ - in particular this means a result row will come back as
+ None (or not be filled into a collection), and new in 0.6
+ also indicates that session.merge() won't issue a round
+ trip to the database for such a PK value. [ticket:1680]
+
+* the mechanics of "backref" have been fully merged into the
+ finer grained "back_populates" system, and take place
+ entirely within the ``_generate_backref()`` method of
+ ``RelationProperty``. This makes the initialization
+ procedure of ``RelationProperty`` simpler and allows
+ easier propagation of settings (such as from subclasses of
+ ``RelationProperty``) into the reverse reference. The
+ internal ``BackRef()`` is gone and ``backref()`` returns a
+ plain tuple that is understood by ``RelationProperty``.
+
+* the keys attribute of ``ResultProxy`` is now a method, so
+ references to it (``result.keys``) must be changed to
+ method invocations (``result.keys()``)
+
+* ``ResultProxy.last_inserted_ids`` is now deprecated, use
+ ``ResultProxy.inserted_primary_key`` instead.
+
+Deprecated/Removed ORM Elements
+-------------------------------
+
+Most elements that were deprecated throughout 0.5 and raised
+deprecation warnings have been removed (with a few
+exceptions). All elements that were marked "pending
+deprecation" are now deprecated and will raise a warning
+upon use.
+
+* 'transactional' flag on sessionmaker() and others is
+ removed. Use 'autocommit=True' to indicate
+ 'transactional=False'.
+
+* 'polymorphic_fetch' argument on mapper() is removed.
+ Loading can be controlled using the 'with_polymorphic'
+ option.
+
+* 'select_table' argument on mapper() is removed. Use
+ 'with_polymorphic=("*", <some selectable>)' for this
+ functionality.
+
+* 'proxy' argument on synonym() is removed. This flag did
+ nothing throughout 0.5, as the "proxy generation"
+ behavior is now automatic.
+
+* Passing a single list of elements to joinedload(),
+ joinedload_all(), contains_eager(), lazyload(), defer(),
+ and undefer() instead of multiple positional \*args is
+ deprecated.
+
+* Passing a single list of elements to query.order_by(),
+ query.group_by(), query.join(), or query.outerjoin()
+ instead of multiple positional \*args is deprecated.
+
+* ``query.iterate_instances()`` is removed. Use
+ ``query.instances()``.
+
+* ``Query.query_from_parent()`` is removed. Use the
+ sqlalchemy.orm.with_parent() function to produce a
+ "parent" clause, or alternatively ``query.with_parent()``.
+
+* ``query._from_self()`` is removed, use
+ ``query.from_self()`` instead.
+
+* the "comparator" argument to composite() is removed. Use
+ "comparator_factory".
+
+* ``RelationProperty._get_join()`` is removed.
+
+
+* the 'echo_uow' flag on Session is removed. Use logging
+ on the "sqlalchemy.orm.unitofwork" name.
+
+* ``session.clear()`` is removed. use
+ ``session.expunge_all()``.
+
+* ``session.save()``, ``session.update()``,
+ ``session.save_or_update()`` are removed. Use
+ ``session.add()`` and ``session.add_all()``.
+
+* the "objects" flag on session.flush() remains deprecated.
+
+
+* the "dont_load=True" flag on session.merge() is deprecated
+ in favor of "load=False".
+
+* ``ScopedSession.mapper`` remains deprecated. See the
+ usage recipe at http://www.sqlalchemy.org/trac/wiki/Usag
+ eRecipes/SessionAwareMapper
+
+* passing an ``InstanceState`` (internal SQLAlchemy state
+ object) to ``attributes.init_collection()`` or
+ ``attributes.get_history()`` is deprecated. These
+ functions are public API and normally expect a regular
+ mapped object instance.
+
+* the 'engine' parameter to ``declarative_base()`` is
+ removed. Use the 'bind' keyword argument.
+
+Extensions
+==========
+
+SQLSoup
+-------
+
+SQLSoup has been modernized and updated to reflect common
+0.5/0.6 capabilities, including well defined session
+integration. Please read the new docs at [http://www.sqlalc
+hemy.org/docs/06/reference/ext/sqlsoup.html].
+
+Declarative
+-----------
+
+The ``DeclarativeMeta`` (default metaclass for
+``declarative_base``) previously allowed subclasses to
+modify ``dict_`` to add class attributes (e.g. columns).
+This no longer works, the ``DeclarativeMeta`` constructor
+now ignores ``dict_``. Instead, the class attributes should
+be assigned directly, e.g. ``cls.id=Column(...)``, or the
+`MixIn class <http://www.sqlalchemy.org/docs/reference/ext/d
+eclarative.html#mix-in-classes>`_ approach should be used
+instead of the metaclass approach.
+
--- /dev/null
+==============================
+What's New in SQLAlchemy 0.7 ?
+==============================
+
+.. admonition:: About this Document
+
+ This document describes changes between SQLAlchemy version 0.6,
+ last released May 5, 2012, and SQLAlchemy version 0.7,
+ undergoing maintenance releases as of October, 2012.
+
+ Document date: July 27, 2011
+
+Introduction
+============
+
+This guide introduces what's new in SQLAlchemy version 0.7,
+and also documents changes which affect users migrating
+their applications from the 0.6 series of SQLAlchemy to 0.7.
+
+To as great a degree as possible, changes are made in such a
+way as to not break compatibility with applications built
+for 0.6. The changes that are necessarily not backwards
+compatible are very few, and all but one, the change to
+mutable attribute defaults, should affect an exceedingly
+small portion of applications - many of the changes regard
+non-public APIs and undocumented hacks some users may have
+been attempting to use.
+
+A second, even smaller class of non-backwards-compatible
+changes is also documented. This class of change regards
+those features and behaviors that have been deprecated at
+least since version 0.5 and have been raising warnings since
+their deprecation. These changes would only affect
+applications that are still using 0.4- or early 0.5-style
+APIs. As the project matures, we have fewer and fewer of
+these kinds of changes with 0.x level releases, which is a
+product of our API having ever fewer features that are less
+than ideal for the use cases they were meant to solve.
+
+An array of existing functionalities have been superseded in
+SQLAlchemy 0.7. There's not much difference between the
+terms "superseded" and "deprecated", except that the former
+has a much weaker suggestion of the old feature would ever
+be removed. In 0.7, features like ``synonym`` and
+``comparable_property``, as well as all the ``Extension``
+and other event classes, have been superseded. But these
+"superseded" features have been re-implemented such that
+their implementations live mostly outside of core ORM code,
+so their continued "hanging around" doesn't impact
+SQLAlchemy's ability to further streamline and refine its
+internals, and we expect them to remain within the API for
+the foreseeable future.
+
+New Features
+============
+
+New Event System
+----------------
+
+SQLAlchemy started early with the ``MapperExtension`` class,
+which provided hooks into the persistence cycle of mappers.
+As SQLAlchemy quickly became more componentized, pushing
+mappers into a more focused configurational role, many more
+"extension", "listener", and "proxy" classes popped up to
+solve various activity-interception use cases in an ad-hoc
+fashion. Part of this was driven by the divergence of
+activities; ``ConnectionProxy`` objects wanted to provide a
+system of rewriting statements and parameters;
+``AttributeExtension`` provided a system of replacing
+incoming values, and ``DDL`` objects had events that could
+be switched off of dialect-sensitive callables.
+
+0.7 re-implements virtually all of these plugin points with
+a new, unified approach, which retains all the
+functionalities of the different systems, provides more
+flexibility and less boilerplate, performs better, and
+eliminates the need to learn radically different APIs for
+each event subsystem. The pre-existing classes
+``MapperExtension``, ``SessionExtension``,
+``AttributeExtension``, ``ConnectionProxy``,
+``PoolListener`` as well as the ``DDLElement.execute_at``
+method are deprecated and now implemented in terms of the
+new system - these APIs remain fully functional and are
+expected to remain in place for the foreseeable future.
+
+The new approach uses named events and user-defined
+callables to associate activities with events. The API's
+look and feel was driven by such diverse sources as JQuery,
+Blinker, and Hibernate, and was also modified further on
+several occasions during conferences with dozens of users on
+Twitter, which appears to have a much higher response rate
+than the mailing list for such questions.
+
+It also features an open-ended system of target
+specification that allows events to be associated with API
+classes, such as for all ``Session`` or ``Engine`` objects,
+with specific instances of API classes, such as for a
+specific ``Pool`` or ``Mapper``, as well as for related
+objects like a user- defined class that's mapped, or
+something as specific as a certain attribute on instances of
+a particular subclass of a mapped parent class. Individual
+listener subsystems can apply wrappers to incoming user-
+defined listener functions which modify how they are called
+- an mapper event can receive either the instance of the
+object being operated upon, or its underlying
+``InstanceState`` object. An attribute event can opt whether
+or not to have the responsibility of returning a new value.
+
+Several systems now build upon the new event API, including
+the new "mutable attributes" API as well as composite
+attributes. The greater emphasis on events has also led to
+the introduction of a handful of new events, including
+attribute expiration and refresh operations, pickle
+loads/dumps operations, completed mapper construction
+operations.
+
+.. seealso::
+
+ :ref:`event_toplevel`
+
+:ticket:`1902`
+
+Hybrid Attributes, implements/supersedes synonym(), comparable_property()
+-------------------------------------------------------------------------
+
+The "derived attributes" example has now been turned into an
+official extension. The typical use case for ``synonym()``
+is to provide descriptor access to a mapped column; the use
+case for ``comparable_property()`` is to be able to return a
+``PropComparator`` from any descriptor. In practice, the
+approach of "derived" is easier to use, more extensible, is
+implemented in a few dozen lines of pure Python with almost
+no imports, and doesn't require the ORM core to even be
+aware of it. The feature is now known as the "Hybrid
+Attributes" extension.
+
+``synonym()`` and ``comparable_property()`` are still part
+of the ORM, though their implementations have been moved
+outwards, building on an approach that is similar to that of
+the hybrid extension, so that the core ORM
+mapper/query/property modules aren't really aware of them
+otherwise.
+
+.. seealso::
+
+ :ref:`hybrids_toplevel`
+
+:ticket:`1903`
+
+Speed Enhancements
+------------------
+
+As is customary with all major SQLA releases, a wide pass
+through the internals to reduce overhead and callcounts has
+been made which further reduces the work needed in common
+scenarios. Highlights of this release include:
+
+* The flush process will now bundle INSERT statements into
+ batches fed to ``cursor.executemany()``, for rows where
+ the primary key is already present. In particular this
+ usually applies to the "child" table on a joined table
+ inheritance configuration, meaning the number of calls to
+ ``cursor.execute`` for a large bulk insert of joined-
+ table objects can be cut in half, allowing native DBAPI
+ optimizations to take place for those statements passed
+ to ``cursor.executemany()`` (such as re-using a prepared
+ statement).
+
+* The codepath invoked when accessing a many-to-one
+ reference to a related object that's already loaded has
+ been greatly simplified. The identity map is checked
+ directly without the need to generate a new ``Query``
+ object first, which is expensive in the context of
+ thousands of in-memory many-to-ones being accessed. The
+ usage of constructed-per-call "loader" objects is also no
+ longer used for the majority of lazy attribute loads.
+
+* The rewrite of composites allows a shorter codepath when
+ mapper internals access mapped attributes within a
+ flush.
+
+* New inlined attribute access functions replace the
+ previous usage of "history" when the "save-update" and
+ other cascade operations need to cascade among the full
+ scope of datamembers associated with an attribute. This
+ reduces the overhead of generating a new ``History``
+ object for this speed-critical operation.
+
+* The internals of the ``ExecutionContext``, the object
+ corresponding to a statement execution, have been
+ inlined and simplified.
+
+* The ``bind_processor()`` and ``result_processor()``
+ callables generated by types for each statement
+ execution are now cached (carefully, so as to avoid memory
+ leaks for ad-hoc types and dialects) for the lifespan of
+ that type, further reducing per-statement call overhead.
+
+* The collection of "bind processors" for a particular
+ ``Compiled`` instance of a statement is also cached on
+ the ``Compiled`` object, taking further advantage of the
+ "compiled cache" used by the flush process to re-use the
+ same compiled form of INSERT, UPDATE, DELETE statements.
+
+A demonstration of callcount reduction including a sample
+benchmark script is at
+http://techspot.zzzeek.org/2010/12/12/a-tale-of-three-
+profiles/
+
+Composites Rewritten
+--------------------
+
+The "composite" feature has been rewritten, like
+``synonym()`` and ``comparable_property()``, to use a
+lighter weight implementation based on descriptors and
+events, rather than building into the ORM internals. This
+allowed the removal of some latency from the mapper/unit of
+work internals, and simplifies the workings of composite.
+The composite attribute now no longer conceals the
+underlying columns it builds upon, which now remain as
+regular attributes. Composites can also act as a proxy for
+``relationship()`` as well as ``Column()`` attributes.
+
+The major backwards-incompatible change of composites is
+that they no longer use the ``mutable=True`` system to
+detect in-place mutations. Please use the `Mutation
+Tracking <http://www.sqlalchemy.org/docs/07/orm/extensions/m
+utable.html>`_ extension to establish in-place change events
+to existing composite usage.
+
+.. seealso::
+
+ :ref:`mapper_composite`
+
+ :ref:`mutable_toplevel`
+
+:ticket:`2008` :ticket:`2024`
+
+More succinct form of query.join(target, onclause)
+--------------------------------------------------
+
+The default method of issuing ``query.join()`` to a target
+with an explicit onclause is now:
+
+::
+
+ query.join(SomeClass, SomeClass.id==ParentClass.some_id)
+
+In 0.6, this usage was considered to be an error, because
+``join()`` accepts multiple arguments corresponding to
+multiple JOIN clauses - the two-argument form needed to be
+in a tuple to disambiguate between single-argument and two-
+argument join targets. In the middle of 0.6 we added
+detection and an error message for this specific calling
+style, since it was so common. In 0.7, since we are
+detecting the exact pattern anyway, and since having to type
+out a tuple for no reason is extremely annoying, the non-
+tuple method now becomes the "normal" way to do it. The
+"multiple JOIN" use case is exceedingly rare compared to the
+single join case, and multiple joins these days are more
+clearly represented by multiple calls to ``join()``.
+
+The tuple form will remain for backwards compatibility.
+
+Note that all the other forms of ``query.join()`` remain
+unchanged:
+
+::
+
+ query.join(MyClass.somerelation)
+ query.join("somerelation")
+ query.join(MyTarget)
+ # ... etc
+
+`Querying with Joins
+<http://www.sqlalchemy.org/docs/07/orm/tutorial.html
+#querying-with-joins>`_
+
+:ticket:`1923`
+
+Mutation event extension, supersedes "mutable=True"
+---------------------------------------------------
+
+A new extension, `Mutation Tracking <http://www.sqlalchemy.o
+rg/docs/07/orm/extensions/mutable.html>`_, provides a
+mechanism by which user-defined datatypes can provide change
+events back to the owning parent or parents. The extension
+includes an approach for scalar database values, such as
+those managed by ``PickleType``, ``postgresql.ARRAY``, or
+other custom ``MutableType`` classes, as well as an approach
+for ORM "composites", those configured using :ref:`composite()
+<mapper_composite>`_.
+
+.. seealso::
+
+ :ref:`mutable_toplevel`
+
+NULLS FIRST / NULLS LAST operators
+----------------------------------
+
+These are implemented as an extension to the ``asc()`` and
+``desc()`` operators, called ``nullsfirst()`` and
+``nullslast()``.
+
+.. seealso::
+
+ :func:`.nullsfirst`
+
+ :func:`.nullslast`
+
+:ticket:`723`
+
+select.distinct(), query.distinct() accepts \*args for Postgresql DISTINCT ON
+-----------------------------------------------------------------------------
+
+This was already available by passing a list of expressions
+to the ``distinct`` keyword argument of ``select()``, the
+``distinct()`` method of ``select()`` and ``Query`` now
+accept positional arguments which are rendered as DISTINCT
+ON when a Postgresql backend is used.
+
+`distinct() <http://www.sqlalchemy.org/docs/07/core/expressi
+on_api.html#sqlalchemy.sql.expression.Select.distinct>`_
+
+`Query.distinct() <http://www.sqlalchemy.org/docs/07/orm/que
+ry.html#sqlalchemy.orm.query.Query.distinct>`_
+
+:ticket:`1069`
+
+``Index()`` can be placed inline inside of ``Table``, ``__table_args__``
+------------------------------------------------------------------------
+
+The Index() construct can be created inline with a Table
+definition, using strings as column names, as an alternative
+to the creation of the index outside of the Table. That is:
+
+::
+
+ Table('mytable', metadata,
+ Column('id',Integer, primary_key=True),
+ Column('name', String(50), nullable=False),
+ Index('idx_name', 'name')
+ )
+
+The primary rationale here is for the benefit of declarative
+``__table_args__``, particularly when used with mixins:
+
+::
+
+ class HasNameMixin(object):
+ name = Column('name', String(50), nullable=False)
+ @declared_attr
+ def __table_args__(cls):
+ return (Index('name'), {})
+
+ class User(HasNameMixin, Base):
+ __tablename__ = 'user'
+ id = Column('id', Integer, primary_key=True)
+
+`Indexes <http://www.sqlalchemy.org/docs/07/core/schema.html
+#indexes>`_
+
+Window Function SQL Construct
+-----------------------------
+
+A "window function" provides to a statement information
+about the result set as it's produced. This allows criteria
+against various things like "row number", "rank" and so
+forth. They are known to be supported at least by
+Postgresql, SQL Server and Oracle, possibly others.
+
+The best introduction to window functions is on Postgresql's
+site, where window functions have been supported since
+version 8.4:
+
+http://www.postgresql.org/docs/9.0/static/tutorial-
+window.html
+
+SQLAlchemy provides a simple construct typically invoked via
+an existing function clause, using the ``over()`` method,
+which accepts ``order_by`` and ``partition_by`` keyword
+arguments. Below we replicate the first example in PG's
+tutorial:
+
+::
+
+ from sqlalchemy.sql import table, column, select, func
+
+ empsalary = table('empsalary',
+ column('depname'),
+ column('empno'),
+ column('salary'))
+
+ s = select([
+ empsalary,
+ func.avg(empsalary.c.salary).
+ over(partition_by=empsalary.c.depname).
+ label('avg')
+ ])
+
+ print s
+
+SQL:
+
+::
+
+ SELECT empsalary.depname, empsalary.empno, empsalary.salary,
+ avg(empsalary.salary) OVER (PARTITION BY empsalary.depname) AS avg
+ FROM empsalary
+
+`sqlalchemy.sql.expression.over <http://www.sqlalchemy.org/d
+ocs/07/core/expression_api.html#sqlalchemy.sql.expression.ov
+er>`_
+
+:ticket:`1844`
+
+execution_options() on Connection accepts "isolation_level" argument
+--------------------------------------------------------------------
+
+This sets the transaction isolation level for a single
+``Connection``, until that ``Connection`` is closed and its
+underlying DBAPI resource returned to the connection pool,
+upon which the isolation level is reset back to the default.
+The default isolation level is set using the
+``isolation_level`` argument to ``create_engine()``.
+
+Transaction isolation support is currently only supported by
+the Postgresql and SQLite backends.
+
+`execution_options() <http://www.sqlalchemy.org/docs/07/core
+/connections.html#sqlalchemy.engine.base.Connection.executio
+n_options>`_
+
+:ticket:`2001`
+
+``TypeDecorator`` works with integer primary key columns
+--------------------------------------------------------
+
+A ``TypeDecorator`` which extends the behavior of
+``Integer`` can be used with a primary key column. The
+"autoincrement" feature of ``Column`` will now recognize
+that the underlying database column is still an integer so
+that lastrowid mechanisms continue to function. The
+``TypeDecorator`` itself will have its result value
+processor applied to newly generated primary keys, including
+those received by the DBAPI ``cursor.lastrowid`` accessor.
+
+:ticket:`2005` :ticket:`2006`
+
+``TypeDecorator`` is present in the "sqlalchemy" import space
+-------------------------------------------------------------
+
+No longer need to import this from ``sqlalchemy.types``,
+it's now mirrored in ``sqlalchemy``.
+
+New Dialects
+------------
+
+Dialects have been added:
+
+* a MySQLdb driver for the Drizzle database:
+
+
+ `Drizzle <http://www.sqlalchemy.org/docs/07/dialects/drizz
+ le.html>`_
+
+* support for the pymysql DBAPI:
+
+
+ `pymsql Notes
+ <http://www.sqlalchemy.org/docs/07/dialects/mysql.html
+ #module-sqlalchemy.dialects.mysql.pymysql>`_
+
+* psycopg2 now works with Python 3
+
+
+Behavioral Changes (Backwards Compatible)
+=========================================
+
+C Extensions Build by Default
+-----------------------------
+
+This is as of 0.7b4. The exts will build if cPython 2.xx
+is detected. If the build fails, such as on a windows
+install, that condition is caught and the non-C install
+proceeds. The C exts won't build if Python 3 or Pypy is
+used.
+
+Query.count() simplified, should work virtually always
+------------------------------------------------------
+
+The very old guesswork which occurred within
+``Query.count()`` has been modernized to use
+``.from_self()``. That is, ``query.count()`` is now
+equivalent to:
+
+::
+
+ query.from_self(func.count(literal_column('1'))).scalar()
+
+Previously, internal logic attempted to rewrite the columns
+clause of the query itself, and upon detection of a
+"subquery" condition, such as a column-based query that
+might have aggregates in it, or a query with DISTINCT, would
+go through a convoluted process of rewriting the columns
+clause. This logic failed in complex conditions,
+particularly those involving joined table inheritance, and
+was long obsolete by the more comprehensive ``.from_self()``
+call.
+
+The SQL emitted by ``query.count()`` is now always of the
+form:
+
+::
+
+ SELECT count(1) AS count_1 FROM (
+ SELECT user.id AS user_id, user.name AS user_name from user
+ ) AS anon_1
+
+that is, the original query is preserved entirely inside of
+a subquery, with no more guessing as to how count should be
+applied.
+
+:ticket:`2093`
+
+To emit a non-subquery form of count()
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+MySQL users have already reported that the MyISAM engine not
+surprisingly falls over completely with this simple change.
+Note that for a simple ``count()`` that optimizes for DBs
+that can't handle simple subqueries, ``func.count()`` should
+be used:
+
+::
+
+ from sqlalchemy import func
+ session.query(func.count(MyClass.id)).scalar()
+
+or for ``count(*)``:
+
+::
+
+ from sqlalchemy import func, literal_column
+ session.query(func.count(literal_column('*'))).select_from(MyClass).scalar()
+
+LIMIT/OFFSET clauses now use bind parameters
+--------------------------------------------
+
+The LIMIT and OFFSET clauses, or their backend equivalents
+(i.e. TOP, ROW NUMBER OVER, etc.), use bind parameters for
+the actual values, for all backends which support it (most
+except for Sybase). This allows better query optimizer
+performance as the textual string for multiple statements
+with differing LIMIT/OFFSET are now identical.
+
+:ticket:`805`
+
+Logging enhancements
+--------------------
+
+Vinay Sajip has provided a patch to our logging system such
+that the "hex string" embedded in logging statements for
+engines and pools is no longer needed to allow the ``echo``
+flag to work correctly. A new system that uses filtered
+logging objects allows us to maintain our current behavior
+of ``echo`` being local to individual engines without the
+need for additional identifying strings local to those
+engines.
+
+:ticket:`1926`
+
+Simplified polymorphic_on assignment
+------------------------------------
+
+The population of the ``polymorphic_on`` column-mapped
+attribute, when used in an inheritance scenario, now occurs
+when the object is constructed, i.e. its ``__init__`` method
+is called, using the init event. The attribute then behaves
+the same as any other column-mapped attribute. Previously,
+special logic would fire off during flush to populate this
+column, which prevented any user code from modifying its
+behavior. The new approach improves upon this in three
+ways: 1. the polymorphic identity is now present on the
+object as soon as its constructed; 2. the polymorphic
+identity can be changed by user code without any difference
+in behavior from any other column-mapped attribute; 3. the
+internals of the mapper during flush are simplified and no
+longer need to make special checks for this column.
+
+:ticket:`1895`
+
+contains_eager() chains across multiple paths (i.e. "all()")
+------------------------------------------------------------
+
+The ```contains_eager()```` modifier now will chain itself
+for a longer path without the need to emit individual
+````contains_eager()``` calls. Instead of:
+
+::
+
+ session.query(A).options(contains_eager(A.b), contains_eager(A.b, B.c))
+
+you can say:
+
+::
+
+ session.query(A).options(contains_eager(A.b, B.c))
+
+:ticket:`2032`
+
+Flushing of orphans that have no parent is allowed
+--------------------------------------------------
+
+We've had a long standing behavior that checks for a so-
+called "orphan" during flush, that is, an object which is
+associated with a ``relationship()`` that specifies "delete-
+orphan" cascade, has been newly added to the session for an
+INSERT, and no parent relationship has been established.
+This check was added years ago to accommodate some test
+cases which tested the orphan behavior for consistency. In
+modern SQLA, this check is no longer needed on the Python
+side. The equivalent behavior of the "orphan check" is
+accomplished by making the foreign key reference to the
+object's parent row NOT NULL, where the database does its
+job of establishing data consistency in the same way SQLA
+allows most other operations to do. If the object's parent
+foreign key is nullable, then the row can be inserted. The
+"orphan" behavior runs when the object was persisted with a
+particular parent, and is then disassociated with that
+parent, leading to a DELETE statement emitted for it.
+
+:ticket:`1912`
+
+Warnings generated when collection members, scalar referents not part of the flush
+----------------------------------------------------------------------------------
+
+Warnings are now emitted when related objects referenced via
+a loaded ``relationship()`` on a parent object marked as
+"dirty" are not present in the current ``Session``.
+
+The ``save-update`` cascade takes effect when objects are
+added to the ``Session``, or when objects are first
+associated with a parent, so that an object and everything
+related to it are usually all present in the same
+``Session``. However, if ``save-update`` cascade is
+disabled for a particular ``relationship()``, then this
+behavior does not occur, and the flush process does not try
+to correct for it, instead staying consistent to the
+configured cascade behavior. Previously, when such objects
+were detected during the flush, they were silently skipped.
+The new behavior is that a warning is emitted, for the
+purposes of alerting to a situation that more often than not
+is the source of unexpected behavior.
+
+:ticket:`1973`
+
+Setup no longer installs a Nose plugin
+--------------------------------------
+
+Since we moved to nose we've used a plugin that installs via
+setuptools, so that the ``nosetests`` script would
+automatically run SQLA's plugin code, necessary for our
+tests to have a full environment. In the middle of 0.6, we
+realized that the import pattern here meant that Nose's
+"coverage" plugin would break, since "coverage" requires
+that it be started before any modules to be covered are
+imported; so in the middle of 0.6 we made the situation
+worse by adding a separate ``sqlalchemy-nose`` package to
+the build to overcome this.
+
+In 0.7 we've done away with trying to get ``nosetests`` to
+work automatically, since the SQLAlchemy module would
+produce a large number of nose configuration options for all
+usages of ``nosetests``, not just the SQLAlchemy unit tests
+themselves, and the additional ``sqlalchemy-nose`` install
+was an even worse idea, producing an extra package in Python
+environments. The ``sqla_nose.py`` script in 0.7 is now
+the only way to run the tests with nose.
+
+:ticket:`1949`
+
+Non-``Table``-derived constructs can be mapped
+----------------------------------------------
+
+A construct that isn't against any ``Table`` at all, like a
+function, can be mapped.
+
+::
+
+ from sqlalchemy import select, func
+ from sqlalchemy.orm import mapper
+
+ class Subset(object):
+ pass
+ selectable = select(["x", "y", "z"]).select_from(func.some_db_function()).alias()
+ mapper(Subset, selectable, primary_key=[selectable.c.x])
+
+:ticket:`1876`
+
+aliased() accepts ``FromClause`` elements
+-----------------------------------------
+
+This is a convenience helper such that in the case a plain
+``FromClause``, such as a ``select``, ``Table`` or ``join``
+is passed to the ``orm.aliased()`` construct, it passes
+through to the ``.alias()`` method of that from construct
+rather than constructing an ORM level ``AliasedClass``.
+
+:ticket:`2018`
+
+Session.connection(), Session.execute() accept 'bind'
+-----------------------------------------------------
+
+This is to allow execute/connection operations to
+participate in the open transaction of an engine explicitly.
+It also allows custom subclasses of ``Session`` that
+implement their own ``get_bind()`` method and arguments to
+use those custom arguments with both the ``execute()`` and
+``connection()`` methods equally.
+
+`Session.connection <http://www.sqlalchemy.org/docs/07/orm/s
+ession.html#sqlalchemy.orm.session.Session.connection>`_
+`Session.execute <http://www.sqlalchemy.org/docs/07/orm/sess
+ion.html#sqlalchemy.orm.session.Session.execute>`_
+
+:ticket:`1996`
+
+Standalone bind parameters in columns clause auto-labeled.
+----------------------------------------------------------
+
+Bind parameters present in the "columns clause" of a select
+are now auto-labeled like other "anonymous" clauses, which
+among other things allows their "type" to be meaningful when
+the row is fetched, as in result row processors.
+
+SQLite - relative file paths are normalized through os.path.abspath()
+---------------------------------------------------------------------
+
+This so that a script that changes the current directory
+will continue to target the same location as subsequent
+SQLite connections are established.
+
+:ticket:`2036`
+
+MS-SQL - ``String``/``Unicode``/``VARCHAR``/``NVARCHAR``/``VARBINARY`` emit "max" for no length
+-----------------------------------------------------------------------------------------------
+
+On the MS-SQL backend, the String/Unicode types, and their
+counterparts VARCHAR/ NVARCHAR, as well as VARBINARY
+(:ticket:`1833`) emit "max" as the length when no length is
+specified. This makes it more compatible with Postgresql's
+VARCHAR type which is similarly unbounded when no length
+specified. SQL Server defaults the length on these types
+to '1' when no length is specified.
+
+Behavioral Changes (Backwards Incompatible)
+===========================================
+
+Note again, aside from the default mutability change, most
+of these changes are \*extremely minor* and will not affect
+most users.
+
+``PickleType`` and ARRAY mutability turned off by default
+---------------------------------------------------------
+
+This change refers to the default behavior of the ORM when
+mapping columns that have either the ``PickleType`` or
+``postgresql.ARRAY`` datatypes. The ``mutable`` flag is now
+set to ``False`` by default. If an existing application uses
+these types and depends upon detection of in-place
+mutations, the type object must be constructed with
+``mutable=True`` to restore the 0.6 behavior:
+
+::
+
+ Table('mytable', metadata,
+ # ....
+
+ Column('pickled_data', PickleType(mutable=True))
+ )
+
+The ``mutable=True`` flag is being phased out, in favor of
+the new `Mutation Tracking <http://www.sqlalchemy.org/docs/0
+7/orm/extensions/mutable.html>`_ extension. This extension
+provides a mechanism by which user-defined datatypes can
+provide change events back to the owning parent or parents.
+
+The previous approach of using ``mutable=True`` does not
+provide for change events - instead, the ORM must scan
+through all mutable values present in a session and compare
+them against their original value for changes every time
+``flush()`` is called, which is a very time consuming event.
+This is a holdover from the very early days of SQLAlchemy
+when ``flush()`` was not automatic and the history tracking
+system was not nearly as sophisticated as it is now.
+
+Existing applications which use ``PickleType``,
+``postgresql.ARRAY`` or other ``MutableType`` subclasses,
+and require in-place mutation detection, should migrate to
+the new mutation tracking system, as ``mutable=True`` is
+likely to be deprecated in the future.
+
+:ticket:`1980`
+
+Mutability detection of ``composite()`` requires the Mutation Tracking Extension
+--------------------------------------------------------------------------------
+
+So-called "composite" mapped attributes, those configured
+using the technique described at `Composite Column Types
+<http://www.sqlalchemy.org/docs/07/orm/mapper_config.html
+#composite-column-types>`_, have been re-implemented such
+that the ORM internals are no longer aware of them (leading
+to shorter and more efficient codepaths in critical
+sections). While composite types are generally intended to
+be treated as immutable value objects, this was never
+enforced. For applications that use composites with
+mutability, the `Mutation Tracking <http://www.sqlalchemy.or
+g/docs/07/orm/extensions/mutable.html>`_ extension offers a
+base class which establishes a mechanism for user-defined
+composite types to send change event messages back to the
+owning parent or parents of each object.
+
+Applications which use composite types and rely upon in-
+place mutation detection of these objects should either
+migrate to the "mutation tracking" extension, or change the
+usage of the composite types such that in-place changes are
+no longer needed (i.e., treat them as immutable value
+objects).
+
+SQLite - the SQLite dialect now uses ``NullPool`` for file-based databases
+--------------------------------------------------------------------------
+
+This change is **99.999% backwards compatible**, unless you
+are using temporary tables across connection pool
+connections.
+
+A file-based SQLite connection is blazingly fast, and using
+``NullPool`` means that each call to ``Engine.connect``
+creates a new pysqlite connection.
+
+Previously, the ``SingletonThreadPool`` was used, which
+meant that all connections to a certain engine in a thread
+would be the same connection. It's intended that the new
+approach is more intuitive, particularly when multiple
+connections are used.
+
+``SingletonThreadPool`` is still the default engine when a
+``:memory:`` database is used.
+
+Note that this change **breaks temporary tables used across
+Session commits**, due to the way SQLite handles temp
+tables. See the note at
+http://www.sqlalchemy.org/docs/dialects/sqlite.html#using-
+temporary-tables-with-sqlite if temporary tables beyond the
+scope of one pool connection are desired.
+
+:ticket:`1921`
+
+``Session.merge()`` checks version ids for versioned mappers
+------------------------------------------------------------
+
+Session.merge() will check the version id of the incoming
+state against that of the database, assuming the mapping
+uses version ids and incoming state has a version_id
+assigned, and raise StaleDataError if they don't match.
+This is the correct behavior, in that if incoming state
+contains a stale version id, it should be assumed the state
+is stale.
+
+If merging data into a versioned state, the version id
+attribute can be left undefined, and no version check will
+take place.
+
+This check was confirmed by examining what Hibernate does -
+both the ``merge()`` and the versioning features were
+originally adapted from Hibernate.
+
+:ticket:`2027`
+
+Tuple label names in Query Improved
+-----------------------------------
+
+This improvement is potentially slightly backwards
+incompatible for an application that relied upon the old
+behavior.
+
+Given two mapped classes ``Foo`` and ``Bar`` each with a
+column ``spam``:
+
+::
+
+
+ qa = session.query(Foo.spam)
+ qb = session.query(Bar.spam)
+
+ qu = qa.union(qb)
+
+The name given to the single column yielded by ``qu`` will
+be ``spam``. Previously it would be something like
+``foo_spam`` due to the way the ``union`` would combine
+things, which is inconsistent with the name ``spam`` in the
+case of a non-unioned query.
+
+:ticket:`1942`
+
+Mapped column attributes reference the most specific column first
+-----------------------------------------------------------------
+
+This is a change to the behavior involved when a mapped
+column attribute references multiple columns, specifically
+when dealing with an attribute on a joined-table subclass
+that has the same name as that of an attribute on the
+superclass.
+
+Using declarative, the scenario is this:
+
+::
+
+ class Parent(Base):
+ __tablename__ = 'parent'
+ id = Column(Integer, primary_key=True)
+
+ class Child(Parent):
+ __tablename__ = 'child'
+ id = Column(Integer, ForeignKey('parent.id'), primary_key=True)
+
+Above, the attribute ``Child.id`` refers to both the
+``child.id`` column as well as ``parent.id`` - this due to
+the name of the attribute. If it were named differently on
+the class, such as ``Child.child_id``, it then maps
+distinctly to ``child.id``, with ``Child.id`` being the same
+attribute as ``Parent.id``.
+
+When the ``id`` attribute is made to reference both
+``parent.id`` and ``child.id``, it stores them in an ordered
+list. An expression such as ``Child.id`` then refers to
+just *one* of those columns when rendered. Up until 0.6,
+this column would be ``parent.id``. In 0.7, it is the less
+surprising ``child.id``.
+
+The legacy of this behavior deals with behaviors and
+restrictions of the ORM that don't really apply anymore; all
+that was needed was to reverse the order.
+
+A primary advantage of this approach is that it's now easier
+to construct ``primaryjoin`` expressions that refer to the
+local column:
+
+::
+
+ class Child(Parent):
+ __tablename__ = 'child'
+ id = Column(Integer, ForeignKey('parent.id'), primary_key=True)
+ some_related = relationship("SomeRelated",
+ primaryjoin="Child.id==SomeRelated.child_id")
+
+ class SomeRelated(Base):
+ __tablename__ = 'some_related'
+ id = Column(Integer, primary_key=True)
+ child_id = Column(Integer, ForeignKey('child.id'))
+
+Prior to 0.7 the ``Child.id`` expression would reference
+``Parent.id``, and it would be necessary to map ``child.id``
+to a distinct attribute.
+
+It also means that a query like this one changes its
+behavior:
+
+::
+
+ session.query(Parent).filter(Child.id > 7)
+
+In 0.6, this would render:
+
+::
+
+ SELECT parent.id AS parent_id
+ FROM parent
+ WHERE parent.id > :id_1
+
+in 0.7, you get:
+
+::
+
+ SELECT parent.id AS parent_id
+ FROM parent, child
+ WHERE child.id > :id_1
+
+which you'll note is a cartesian product - this behavior is
+now equivalent to that of any other attribute that is local
+to ``Child``. The ``with_polymorphic()`` method, or a
+similar strategy of explicitly joining the underlying
+``Table`` objects, is used to render a query against all
+``Parent`` objects with criteria against ``Child``, in the
+same manner as that of 0.5 and 0.6:
+
+::
+
+ print s.query(Parent).with_polymorphic([Child]).filter(Child.id > 7)
+
+Which on both 0.6 and 0.7 renders:
+
+::
+
+ SELECT parent.id AS parent_id, child.id AS child_id
+ FROM parent LEFT OUTER JOIN child ON parent.id = child.id
+ WHERE child.id > :id_1
+
+Another effect of this change is that a joined-inheritance
+load across two tables will populate from the child table's
+value, not that of the parent table. An unusual case is that
+a query against "Parent" using ``with_polymorphic="*"``
+issues a query against "parent", with a LEFT OUTER JOIN to
+"child". The row is located in "Parent", sees the
+polymorphic identity corresponds to "Child", but suppose the
+actual row in "child" has been *deleted*. Due to this
+corruption, the row comes in with all the columns
+corresponding to "child" set to NULL - this is now the value
+that gets populated, not the one in the parent table.
+
+:ticket:`1892`
+
+Mapping to joins with two or more same-named columns requires explicit declaration
+----------------------------------------------------------------------------------
+
+This is somewhat related to the previous change in
+:ticket:`1892`. When mapping to a join, same-named columns
+must be explicitly linked to mapped attributes, i.e. as
+described in `Mapping a Class Against Multiple Tables <http:
+//www.sqlalchemy.org/docs/07/orm/mapper_config.html#mapping-
+a-class-against-multiple-tables>`_.
+
+Given two tables ``foo`` and ``bar``, each with a primary
+key column ``id``, the following now produces an error:
+
+::
+
+
+ foobar = foo.join(bar, foo.c.id==bar.c.foo_id)
+ mapper(FooBar, foobar)
+
+This because the ``mapper()`` refuses to guess what column
+is the primary representation of ``FooBar.id`` - is it
+``foo.c.id`` or is it ``bar.c.id`` ? The attribute must be
+explicit:
+
+::
+
+
+ foobar = foo.join(bar, foo.c.id==bar.c.foo_id)
+ mapper(FooBar, foobar, properties={
+ 'id':[foo.c.id, bar.c.id]
+ })
+
+:ticket:`1896`
+
+Mapper requires that polymorphic_on column be present in the mapped selectable
+------------------------------------------------------------------------------
+
+This is a warning in 0.6, now an error in 0.7. The column
+given for ``polymorphic_on`` must be in the mapped
+selectable. This to prevent some occasional user errors
+such as:
+
+::
+
+ mapper(SomeClass, sometable, polymorphic_on=some_lookup_table.c.id)
+
+where above the polymorphic_on needs to be on a
+``sometable`` column, in this case perhaps
+``sometable.c.some_lookup_id``. There are also some
+"polymorphic union" scenarios where similar mistakes
+sometimes occur.
+
+Such a configuration error has always been "wrong", and the
+above mapping doesn't work as specified - the column would
+be ignored. It is however potentially backwards
+incompatible in the rare case that an application has been
+unknowingly relying upon this behavior.
+
+:ticket:`1875`
+
+``DDL()`` constructs now escape percent signs
+---------------------------------------------
+
+Previously, percent signs in ``DDL()`` strings would have to
+be escaped, i.e. ``%%`` depending on DBAPI, for those DBAPIs
+that accept ``pyformat`` or ``format`` binds (i.e. psycopg2,
+mysql-python), which was inconsistent versus ``text()``
+constructs which did this automatically. The same escaping
+now occurs for ``DDL()`` as for ``text()``.
+
+:ticket:`1897`
+
+``Table.c`` / ``MetaData.tables`` refined a bit, don't allow direct mutation
+----------------------------------------------------------------------------
+
+Another area where some users were tinkering around in such
+a way that doesn't actually work as expected, but still left
+an exceedingly small chance that some application was
+relying upon this behavior, the construct returned by the
+``.c`` attribute on ``Table`` and the ``.tables`` attribute
+on ``MetaData`` is explicitly non-mutable. The "mutable"
+version of the construct is now private. Adding columns to
+``.c`` involves using the ``append_column()`` method of
+``Table``, which ensures things are associated with the
+parent ``Table`` in the appropriate way; similarly,
+``MetaData.tables`` has a contract with the ``Table``
+objects stored in this dictionary, as well as a little bit
+of new bookkeeping in that a ``set()`` of all schema names
+is tracked, which is satisfied only by using the public
+``Table`` constructor as well as ``Table.tometadata()``.
+
+It is of course possible that the ``ColumnCollection`` and
+``dict`` collections consulted by these attributes could
+someday implement events on all of their mutational methods
+such that the appropriate bookkeeping occurred upon direct
+mutation of the collections, but until someone has the
+motivation to implement all that along with dozens of new
+unit tests, narrowing the paths to mutation of these
+collections will ensure no application is attempting to rely
+upon usages that are currently not supported.
+
+:ticket:`1893` :ticket:`1917`
+
+server_default consistently returns None for all inserted_primary_key values
+----------------------------------------------------------------------------
+
+Established consistency when server_default is present on an
+Integer PK column. SQLA doesn't pre-fetch these, nor do they
+come back in cursor.lastrowid (DBAPI). Ensured all backends
+consistently return None in result.inserted_primary_key for
+these - some backends may have returned a value previously.
+Using a server_default on a primary key column is extremely
+unusual. If a special function or SQL expression is used
+to generate primary key defaults, this should be established
+as a Python-side "default" instead of server_default.
+
+Regarding reflection for this case, reflection of an int PK
+col with a server_default sets the "autoincrement" flag to
+False, except in the case of a PG SERIAL col where we
+detected a sequence default.
+
+:ticket:`2020` :ticket:`2021`
+
+The ``sqlalchemy.exceptions`` alias in sys.modules is removed
+-------------------------------------------------------------
+
+For a few years we've added the string
+``sqlalchemy.exceptions`` to ``sys.modules``, so that a
+statement like "``import sqlalchemy.exceptions``" would
+work. The name of the core exceptions module has been
+``exc`` for a long time now, so the recommended import for
+this module is:
+
+::
+
+ from sqlalchemy import exc
+
+The ``exceptions`` name is still present in "``sqlalchemy``"
+for applications which might have said ``from sqlalchemy
+import exceptions``, but they should also start using the
+``exc`` name.
+
+Query Timing Recipe Changes
+---------------------------
+
+While not part of SQLAlchemy itself, it's worth mentioning
+that the rework of the ``ConnectionProxy`` into the new
+event system means it is no longer appropriate for the
+"Timing all Queries" recipe. Please adjust query-timers to
+use the ``before_cursor_execute()`` and
+``after_cursor_execute()`` events, demonstrated in the
+updated recipe UsageRecipes/Profiling.
+
+Deprecated API
+==============
+
+Default constructor on types will not accept arguments
+------------------------------------------------------
+
+Simple types like ``Integer``, ``Date`` etc. in the core
+types module don't accept arguments. The default
+constructor that accepts/ignores a catchall ``\*args,
+\**kwargs`` is restored as of 0.7b4/0.7.0, but emits a
+deprecation warning.
+
+If arguments are being used with a core type like
+``Integer``, it may be that you intended to use a dialect
+specific type, such as ``sqlalchemy.dialects.mysql.INTEGER``
+which does accept a "display_width" argument for example.
+
+compile_mappers() renamed configure_mappers(), simplified configuration internals
+---------------------------------------------------------------------------------
+
+This system slowly morphed from something small, implemented
+local to an individual mapper, and poorly named into
+something that's more of a global "registry-" level function
+and poorly named, so we've fixed both by moving the
+implementation out of ``Mapper`` altogether and renaming it
+to ``configure_mappers()``. It is of course normally not
+needed for an application to call ``configure_mappers()`` as
+this process occurs on an as-needed basis, as soon as the
+mappings are needed via attribute or query access.
+
+:ticket:`1966`
+
+Core listener/proxy superseded by event listeners
+-------------------------------------------------
+
+``PoolListener``, ``ConnectionProxy``,
+``DDLElement.execute_at`` are superseded by
+``event.listen()``, using the ``PoolEvents``,
+``EngineEvents``, ``DDLEvents`` dispatch targets,
+respectively.
+
+ORM extensions superseded by event listeners
+--------------------------------------------
+
+``MapperExtension``, ``AttributeExtension``,
+``SessionExtension`` are superseded by ``event.listen()``,
+using the ``MapperEvents``/``InstanceEvents``,
+``AttributeEvents``, ``SessionEvents``, dispatch targets,
+respectively.
+
+Sending a string to 'distinct' in select() for MySQL should be done via prefixes
+--------------------------------------------------------------------------------
+
+This obscure feature allows this pattern with the MySQL
+backend:
+
+::
+
+ select([mytable], distinct='ALL', prefixes=['HIGH_PRIORITY'])
+
+The ``prefixes`` keyword or ``prefix_with()`` method should
+be used for non-standard or unusual prefixes:
+
+::
+
+ select([mytable]).prefix_with('HIGH_PRIORITY', 'ALL')
+
+``useexisting`` superseded by ``extend_existing`` and ``keep_existing``
+-----------------------------------------------------------------------
+
+The ``useexisting`` flag on Table has been superseded by a
+new pair of flags ``keep_existing`` and ``extend_existing``.
+``extend_existing`` is equivalent to ``useexisting`` - the
+existing Table is returned, and additional constructor
+elements are added. With ``keep_existing``, the existing
+Table is returned, but additional constructor elements are
+not added - these elements are only applied when the Table
+is newly created.
+
+Backwards Incompatible API Changes
+==================================
+
+Callables passed to ``bindparam()`` don't get evaluated - affects the Beaker example
+------------------------------------------------------------------------------------
+
+:ticket:`1950`
+
+Note this affects the Beaker caching example, where the
+workings of the ``_params_from_query()`` function needed a
+slight adjustment. If you're using code from the Beaker
+example, this change should be applied.
+
+types.type_map is now private, types._type_map
+----------------------------------------------
+
+We noticed some users tapping into this dictionary inside of
+``sqlalchemy.types`` as a shortcut to associating Python
+types with SQL types. We can't guarantee the contents or
+format of this dictionary, and additionally the business of
+associating Python types in a one-to-one fashion has some
+grey areas that should are best decided by individual
+applications, so we've underscored this attribute.
+
+:ticket:`1870`
+
+Renamed the ``alias`` keyword arg of standalone ``alias()`` function to ``name``
+--------------------------------------------------------------------------------
+
+This so that the keyword argument ``name`` matches that of
+the ``alias()`` methods on all ``FromClause`` objects as
+well as the ``name`` argument on ``Query.subquery()``.
+
+Only code that uses the standalone ``alias()`` function, and
+not the method bound functions, and passes the alias name
+using the explicit keyword name ``alias``, and not
+positionally, would need modification here.
+
+Non-public ``Pool`` methods underscored
+---------------------------------------
+
+All methods of ``Pool`` and subclasses which are not
+intended for public use have been renamed with underscores.
+That they were not named this way previously was a bug.
+
+Pooling methods now underscored or removed:
+
+``Pool.create_connection()`` ->
+``Pool._create_connection()``
+
+``Pool.do_get()`` -> ``Pool._do_get()``
+
+``Pool.do_return_conn()`` -> ``Pool._do_return_conn()``
+
+``Pool.do_return_invalid()`` -> removed, was not used
+
+``Pool.return_conn()`` -> ``Pool._return_conn()``
+
+``Pool.get()`` -> ``Pool._get()``, public API is
+``Pool.connect()``
+
+``SingletonThreadPool.cleanup()`` -> ``_cleanup()``
+
+``SingletonThreadPool.dispose_local()`` -> removed, use
+``conn.invalidate()``
+
+:ticket:`1982`
+
+Previously Deprecated, Now Removed
+==================================
+
+Query.join(), Query.outerjoin(), eagerload(), eagerload_all(), others no longer allow lists of attributes as arguments
+----------------------------------------------------------------------------------------------------------------------
+
+Passing a list of attributes or attribute names to
+``Query.join``, ``eagerload()``, and similar has been
+deprecated since 0.5:
+
+::
+
+ # old way, deprecated since 0.5
+ session.query(Houses).join([Houses.rooms, Room.closets])
+ session.query(Houses).options(eagerload_all([Houses.rooms, Room.closets]))
+
+These methods all accept \*args as of the 0.5 series:
+
+::
+
+ # current way, in place since 0.5
+ session.query(Houses).join(Houses.rooms, Room.closets)
+ session.query(Houses).options(eagerload_all(Houses.rooms, Room.closets))
+
+``ScopedSession.mapper`` is removed
+-----------------------------------
+
+This feature provided a mapper extension which linked class-
+based functionality with a particular ``ScopedSession``, in
+particular providing the behavior such that new object
+instances would be automatically associated with that
+session. The feature was overused by tutorials and
+frameworks which led to great user confusion due to its
+implicit behavior, and was deprecated in 0.5.5. Techniques
+for replicating its functionality are at
+[wiki:UsageRecipes/SessionAwareMapper]
+
# All configuration values have a default; values that are commented out
# serve to show the default.
-import sys, os
+import sys
+import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# 'sphinx.ext.doctest', 'builder.builders']
extensions = ['sphinx.ext.autodoc',
- 'sphinx.ext.doctest', 'builder.builders']
+ 'sphinx.ext.doctest',
+ 'sphinx.ext.doctest',
+ 'builder.autodoc_mods',
+ 'builder.changelog',
+ 'builder.dialect_info',
+ 'builder.mako',
+ 'builder.sqlformatter',
+ ]
# Add any paths that contain templates here, relative to this directory.
# not sure why abspath() is needed here, some users
# The suffix of source filenames.
source_suffix = '.rst'
-template_bridge = "builder.builders.MakoBridge"
+# section names used by the changelog extension.
+changelog_sections = ["general", "orm", "orm declarative", "orm querying", \
+ "orm configuration", "engine", "sql", \
+ "schema", \
+ "postgresql", "mysql", "sqlite", "mssql", \
+ "oracle", "firebird"]
+# tags to sort on inside of sections
+changelog_inner_tag_sort = ["feature", "bug", "moved", "changed", "removed"]
+
+# how to render changelog links
+changelog_render_ticket = "http://www.sqlalchemy.org/trac/ticket/%s"
+changelog_render_pullreq = "https://bitbucket.org/sqlalchemy/sqlalchemy/pull-request/%s"
+changelog_render_changeset = "http://www.sqlalchemy.org/trac/changeset/%s"
# The encoding of source files.
#source_encoding = 'utf-8-sig'
A high level view and getting set up.
:ref:`Overview <overview>` |
-:ref:`Installation Guide <installation>` |
-:ref:`Migration from 0.6 <migration>`
+:ref:`Installation Guide <installation>` |
+:doc:`Migration from 0.6 <changelog/migration_07>` |
+:doc:`Changelog catalog <changelog/index>`
SQLAlchemy ORM
==============
0.6 to 0.7 Migration
=====================
-Notes on what's changed from 0.6 to 0.7 is available on the SQLAlchemy wiki at
-`07Migration <http://www.sqlalchemy.org/trac/wiki/07Migration>`_.
+Notes on what's changed from 0.6 to 0.7 is available at :doc:`changelog/migration_07`.
}
a {
- font-weight:normal;
+ font-weight:normal;
text-decoration:none;
}
/* paragraph links after sections.
These aren't visible until hovering
- over the <h> tag, then have a
+ over the <h> tag, then have a
"reverse video" effect over the actual
link
*/
#docs-body h1 {
/* hide the <h1> for each content section. */
display:none;
- font-size:1.8em;
+ font-size:2.0em;
}
#docs-body h2 {
- font-size:1.6em;
+ font-size:1.8em;
+ border-top:1px solid;
+ /*border-bottom:1px solid;*/
+ padding-top:20px;
}
+#sqlalchemy-documentation h2 {
+ border-top:none;
+ padding-top:0;
+}
#docs-body h3 {
font-size:1.4em;
}
}
#docs-container pre {
- background-color: #f0f0f0;
+ background-color: #f0f0f0;
border: solid 1px #ccc;
box-shadow: 2px 2px 3px #DFDFDF;
padding:10px;
line-height:1.2em;
}
-#docs-container a.sql_link,
+#docs-container a.sql_link,
#docs-container .sql_link
{
text-decoration: none;
background-color: #900;
}
+/* changeset stuff */
+
+#docs-container a.changeset-link {
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+}
+
/* docutils-specific elements */
th.field-name {
text-align:right;
}
-div.note, div.warning, p.deprecated, div.topic {
+div.note, div.warning, p.deprecated, div.topic, div.admonition {
background-color:#EEFFEF;
}
border:1px solid #CCCCCC;
padding:5px 10px;
font-size:.9em;
+ margin-top:5px;
+ box-shadow: 2px 2px 3px #DFDFDF;
+}
+
+div.inherited-member {
+ border:1px solid #CCCCCC;
+ padding:5px 5px;
+ font-size:.9em;
box-shadow: 2px 2px 3px #DFDFDF;
}
font-size:1.1em;
}
+
dt:target, span.highlight {
background-color:#FBE54E;
}
.go {color:#804049;}
-/* special "index page" sections
+/* special "index page" sections
with specific formatting
*/
useobject=True)
return Foo, Bar
- def _someattr_history(self, f):
+ def _someattr_history(self, f, **kw):
return attributes.get_state_history(
attributes.instance_state(f),
- 'someattr')
+ 'someattr', **kw)
def _commit_someattr(self, f):
attributes.instance_state(f).commit(attributes.instance_dict(f),
assert 'someattr' not in f.__dict__
assert 'someattr' not in attributes.instance_state(f).committed_state
+ def test_collection_never_set(self):
+ Foo = self._fixture(uselist=True, useobject=True,
+ active_history=True)
+ f = Foo()
+ eq_(self._someattr_history(f, passive=True), ((), [], ()))
+
def test_scalar_active_set(self):
Foo = self._fixture(uselist=False, useobject=False,
active_history=True)