summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-03-03 21:02:26 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-03-03 21:02:26 +0000
commite736817a92797a3a3ce7b1c2cc9622643186f65b (patch)
treed8af6807cd998cf6bc3e5d78428259a49a7c01c6 /lib/sqlalchemy/sql.py
parentc8a78834f5a11394105942f9c8d9483451415e12 (diff)
downloadsqlalchemy-e736817a92797a3a3ce7b1c2cc9622643186f65b.tar.gz
- 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.
Diffstat (limited to 'lib/sqlalchemy/sql.py')
-rw-r--r--lib/sqlalchemy/sql.py49
1 files changed, 33 insertions, 16 deletions
diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py
index 9c8d5db08..da1afe799 100644
--- a/lib/sqlalchemy/sql.py
+++ b/lib/sqlalchemy/sql.py
@@ -308,7 +308,7 @@ def literal(value, type=None):
for this literal.
"""
- return _BindParamClause('literal', value, type=type)
+ return _BindParamClause('literal', value, type=type, unique=True)
def label(name, obj):
"""Return a ``_Label`` object for the given selectable, used in
@@ -343,19 +343,30 @@ def table(name, *columns):
return TableClause(name, *columns)
-def bindparam(key, value=None, type=None, shortname=None):
+def bindparam(key, value=None, type=None, shortname=None, unique=False):
"""Create a bind parameter clause with the given key.
- An optional default value can be specified by the value parameter,
- and the optional type parameter is a
- ``sqlalchemy.types.TypeEngine`` object which indicates
- bind-parameter and result-set translation for this bind parameter.
+ value
+ a default value for this bind parameter. a bindparam with a value
+ is called a ``value-based bindparam``.
+
+ shortname
+ an ``alias`` for this bind parameter. usually used to alias the ``key`` and
+ ``label`` of a column, i.e. ``somecolname`` and ``sometable_somecolname``
+
+ type
+ a sqlalchemy.types.TypeEngine object indicating the type of this bind param, will
+ invoke type-specific bind parameter processing
+
+ unique
+ if True, bind params sharing the same name will have their underlying ``key`` modified
+ to a uniquely generated name. mostly useful with value-based bind params.
"""
if isinstance(key, _ColumnClause):
- return _BindParamClause(key.name, value, type=key.type, shortname=shortname)
+ return _BindParamClause(key.name, value, type=key.type, shortname=shortname, unique=unique)
else:
- return _BindParamClause(key, value, type=type, shortname=shortname)
+ return _BindParamClause(key, value, type=type, shortname=shortname, unique=unique)
def text(text, engine=None, *args, **kwargs):
"""Create literal text to be inserted into a query.
@@ -817,7 +828,7 @@ class _CompareMixin(object):
return self._operate('/', other)
def _bind_param(self, obj):
- return _BindParamClause('literal', obj, shortname=None, type=self.type)
+ return _BindParamClause('literal', obj, shortname=None, type=self.type, unique=True)
def _check_literal(self, other):
if _is_literal(other):
@@ -1120,7 +1131,7 @@ class _BindParamClause(ClauseElement, _CompareMixin):
Public constructor is the ``bindparam()`` function.
"""
- def __init__(self, key, value, shortname=None, type=None):
+ def __init__(self, key, value, shortname=None, type=None, unique=False):
"""Construct a _BindParamClause.
key
@@ -1144,15 +1155,21 @@ class _BindParamClause(ClauseElement, _CompareMixin):
corresponding ``_BindParamClause`` objects.
type
-
A ``TypeEngine`` object that will be used to pre-process the
value corresponding to this ``_BindParamClause`` at
execution time.
+
+ unique
+ if True, the key name of this BindParamClause will be
+ modified if another ``_BindParamClause`` of the same
+ name already has been located within the containing
+ ``ClauseElement``.
"""
self.key = key
self.value = value
self.shortname = shortname or key
+ self.unique = unique
self.type = sqltypes.to_instance(type)
def accept_visitor(self, visitor):
@@ -1162,7 +1179,7 @@ class _BindParamClause(ClauseElement, _CompareMixin):
return []
def copy_container(self):
- return _BindParamClause(self.key, self.value, self.shortname, self.type)
+ return _BindParamClause(self.key, self.value, self.shortname, self.type, unique=self.unique)
def typeprocess(self, value, dialect):
return self.type.dialect_impl(dialect).convert_bind_param(value, dialect)
@@ -1353,7 +1370,7 @@ class _CalculatedClause(ClauseList, ColumnElement):
visitor.visit_calculatedclause(self)
def _bind_param(self, obj):
- return _BindParamClause(self.name, obj, type=self.type)
+ return _BindParamClause(self.name, obj, type=self.type, unique=True)
def select(self):
return select([self])
@@ -1388,7 +1405,7 @@ class _Function(_CalculatedClause, FromClause):
if clause is None:
clause = null()
else:
- clause = _BindParamClause(self.name, clause, shortname=self.name, type=None)
+ clause = _BindParamClause(self.name, clause, shortname=self.name, type=None, unique=True)
self.clauses.append(clause)
def copy_container(self):
@@ -1753,7 +1770,7 @@ class _ColumnClause(ColumnElement):
return []
def _bind_param(self, obj):
- return _BindParamClause(self._label, obj, shortname = self.name, type=self.type)
+ return _BindParamClause(self._label, obj, shortname = self.name, type=self.type, unique=True)
def _make_proxy(self, selectable, name = None):
# propigate the "is_literal" flag only if we are keeping our name,
@@ -2208,7 +2225,7 @@ class _UpdateBase(ClauseElement):
else:
col = key
try:
- parameters[key] = bindparam(col, value)
+ parameters[key] = bindparam(col, value, unique=True)
except KeyError:
del parameters[key]
return parameters