summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/schema.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/schema.py')
-rw-r--r--lib/sqlalchemy/schema.py94
1 files changed, 67 insertions, 27 deletions
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py
index f4e89ef24..6fc10c6cb 100644
--- a/lib/sqlalchemy/schema.py
+++ b/lib/sqlalchemy/schema.py
@@ -29,6 +29,8 @@ class SchemaItem(object):
for item in args:
if item is not None:
item._set_parent(self)
+ def _get_parent(self):
+ raise NotImplementedError()
def _set_parent(self, parent):
"""associate with this SchemaItem's parent object."""
raise NotImplementedError()
@@ -39,6 +41,29 @@ class SchemaItem(object):
return None
def _get_engine(self):
return self._derived_metadata().engine
+
+ def _set_casing_strategy(self, name, kwargs, keyname='case_sensitive'):
+ setattr(self, '_SchemaItem__%s_setting' % keyname, kwargs.pop(keyname, None))
+ def _determine_case_sensitive(self, name, keyname='case_sensitive'):
+ local = getattr(self, '_SchemaItem__%s_setting' % keyname, None)
+ if local is not None:
+ return local
+ parent = self
+ while parent is not None:
+ parent = parent._get_parent()
+ if parent is not None:
+ parentval = getattr(parent, '_SchemaItem__case_sensitive_setting', None)
+ if parentval is not None:
+ return parentval
+ return name is not None and name.lower() != name
+ def _get_case_sensitive(self):
+ try:
+ return self.__case_sensitive
+ except AttributeError:
+ self.__case_sensitive = self._determine_case_sensitive(self.name)
+ return self.__case_sensitive
+ case_sensitive = property(_get_case_sensitive)
+
engine = property(lambda s:s._get_engine())
metadata = property(lambda s:s._derived_metadata())
@@ -153,10 +178,10 @@ class Table(SchemaItem, sql.TableClause):
quote_schema=False : indicates that the Namespace identifier must be properly escaped and quoted before being sent
to the database. This flag overrides all other quoting behavior.
- natural_case=True : indicates that the identifier should be interpreted by the database in the natural case for identifiers.
+ case_sensitive=True : indicates that the identifier should be interpreted by the database in the natural case for identifiers.
Mixed case is not sufficient to cause this identifier to be quoted; it must contain an illegal character.
- natural_case_schema=True : indicates that the identifier should be interpreted by the database in the natural case for identifiers.
+ case_sensitive_schema=True : indicates that the identifier should be interpreted by the database in the natural case for identifiers.
Mixed case is not sufficient to cause this identifier to be quoted; it must contain an illegal character.
"""
super(Table, self).__init__(name)
@@ -165,21 +190,26 @@ class Table(SchemaItem, sql.TableClause):
self.indexes = util.OrderedProperties()
self.constraints = []
self.primary_key = PrimaryKeyConstraint()
-
+ self.quote = kwargs.get('quote', False)
+ self.quote_schema = kwargs.get('quote_schema', False)
if self.schema is not None:
self.fullname = "%s.%s" % (self.schema, self.name)
else:
self.fullname = self.name
self.owner = kwargs.pop('owner', None)
- self.quote = kwargs.pop('quote', False)
- self.quote_schema = kwargs.pop('quote_schema', False)
- default_natural_case = metadata.natural_case
- if default_natural_case is None:
- default_natural_case = True
- self.natural_case = kwargs.pop('natural_case', default_natural_case)
- self.natural_case_schema = kwargs.pop('natural_case_schema', default_natural_case)
+
+ self._set_casing_strategy(name, kwargs)
+ self._set_casing_strategy(self.schema or '', kwargs, keyname='case_sensitive_schema')
self.kwargs = kwargs
+ def _get_case_sensitive_schema(self):
+ try:
+ return getattr(self, '_SchemaItem__case_sensitive_schema')
+ except AttributeError:
+ setattr(self, '_SchemaItem__case_sensitive_schema', self._determine_case_sensitive(self.schema or '', keyname='case_sensitive_schema'))
+ return getattr(self, '_SchemaItem__case_sensitive_schema')
+ case_sensitive_schema = property(_get_case_sensitive_schema)
+
def _set_primary_key(self, pk):
if getattr(self, '_primary_key', None) in self.constraints:
self.constraints.remove(self._primary_key)
@@ -220,7 +250,9 @@ class Table(SchemaItem, sql.TableClause):
def append_index(self, index):
self.indexes[index.name] = index
-
+
+ def _get_parent(self):
+ return self._metadata
def _set_parent(self, metadata):
metadata.tables[_get_table_key(self.name, self.schema)] = self
self._metadata = metadata
@@ -348,7 +380,7 @@ class Column(SchemaItem, sql.ColumnClause):
quote=False : indicates that the Column identifier must be properly escaped and quoted before being sent
to the database.
- natural_case=True : indicates that the identifier should be interpreted by the database in the natural case for identifiers.
+ case_sensitive=True : indicates that the identifier should be interpreted by the database in the natural case for identifiers.
Mixed case is not sufficient to cause this identifier to be quoted; it must contain an illegal character.
"""
name = str(name) # in case of incoming unicode
@@ -362,7 +394,7 @@ class Column(SchemaItem, sql.ColumnClause):
self.index = kwargs.pop('index', None)
self.unique = kwargs.pop('unique', None)
self.quote = kwargs.pop('quote', False)
- self.natural_case = kwargs.pop('natural_case', True)
+ self._set_casing_strategy(name, kwargs)
self.onupdate = kwargs.pop('onupdate', None)
if self.index is not None and self.unique is not None:
raise exceptions.ArgumentError("Column may not define both index and unique")
@@ -405,13 +437,13 @@ class Column(SchemaItem, sql.ColumnClause):
self.primary_key = True
self.nullable = False
self.table.primary_key.append(self)
-
+
+ def _get_parent(self):
+ return self.table
def _set_parent(self, table):
if getattr(self, 'table', None) is not None:
raise exceptions.ArgumentError("this Column already has a table!")
table.append_column(self)
- if self.table.metadata.natural_case is not None:
- self.natural_case = self.table.metadata.natural_case
if self.index or self.unique:
table.append_index_column(self, index=self.index,
unique=self.unique)
@@ -427,7 +459,7 @@ class Column(SchemaItem, sql.ColumnClause):
def copy(self):
"""creates a copy of this Column, unitialized"""
- return Column(self.name, self.type, self.default, key = self.key, primary_key = self.primary_key, nullable = self.nullable, hidden = self.hidden)
+ return Column(self.name, self.type, self.default, key = self.key, primary_key = self.primary_key, nullable = self.nullable, hidden = self.hidden, case_sensitive=self.case_sensitive, quote=self.quote)
def _make_proxy(self, selectable, name = None):
"""creates a copy of this Column, initialized the way this Column is"""
@@ -435,7 +467,7 @@ class Column(SchemaItem, sql.ColumnClause):
fk = None
else:
fk = self.foreign_key.copy()
- c = Column(name or self.name, self.type, fk, self.default, key = name or self.key, primary_key = self.primary_key, nullable = self.nullable, hidden = self.hidden)
+ c = Column(name or self.name, self.type, fk, self.default, key = name or self.key, primary_key = self.primary_key, nullable = self.nullable, hidden = self.hidden, case_sensitive=self.case_sensitive, quote=self.quote)
c.table = selectable
c.orig_set = self.orig_set
c._parent = self
@@ -539,7 +571,9 @@ class ForeignKey(SchemaItem):
def accept_schema_visitor(self, visitor):
"""calls the visit_foreign_key method on the given visitor."""
visitor.visit_foreign_key(self)
-
+
+ def _get_parent(self):
+ return self.parent
def _set_parent(self, column):
self.parent = column
@@ -565,6 +599,8 @@ class DefaultGenerator(SchemaItem):
return self.column.table.metadata
except AttributeError:
return self._metadata
+ def _get_parent(self):
+ return self.column
def _set_parent(self, column):
self.column = column
self._metadata = self.column.table.metadata
@@ -604,14 +640,14 @@ class ColumnDefault(DefaultGenerator):
class Sequence(DefaultGenerator):
"""represents a sequence, which applies to Oracle and Postgres databases."""
- def __init__(self, name, start = None, increment = None, optional=False, quote=False, natural_case=True, **kwargs):
+ def __init__(self, name, start = None, increment = None, optional=False, quote=False, **kwargs):
super(Sequence, self).__init__(**kwargs)
self.name = name
self.start = start
self.increment = increment
self.optional=optional
- self.natural_case = natural_case
self.quote = quote
+ self._set_casing_strategy(name, kwargs)
def __repr__(self):
return "Sequence(%s)" % string.join(
[repr(self.name)] +
@@ -620,8 +656,6 @@ class Sequence(DefaultGenerator):
def _set_parent(self, column):
super(Sequence, self)._set_parent(column)
column.sequence = self
- if column.metadata.natural_case is not None:
- self.natural_case = column.metadata.natural_case
def create(self):
self.engine.create(self)
return self
@@ -652,6 +686,8 @@ class Constraint(SchemaItem):
self.columns[index] = item
def copy(self):
raise NotImplementedError()
+ def _get_parent(self):
+ return self.table
class ForeignKeyConstraint(Constraint):
"""table-level foreign key constraint, represents a colleciton of ForeignKey objects."""
@@ -684,6 +720,7 @@ class PrimaryKeyConstraint(Constraint):
super(PrimaryKeyConstraint, self).__init__(name=kwargs.pop('name', None))
self.__colnames = list(columns)
def _set_parent(self, table):
+ self.table = table
table.primary_key = self
for c in self.__colnames:
self.append(table.c[c])
@@ -700,6 +737,7 @@ class UniqueConstraint(Constraint):
super(Constraint, self).__init__(name)
self.__colnames = list(columns)
def _set_parent(self, table):
+ self.table = table
table.constraints.append(self)
for c in self.__colnames:
self.append(table.c[c])
@@ -734,7 +772,8 @@ class Index(SchemaItem):
def _init_items(self, *args):
for column in args:
self.append_column(column)
-
+ def _get_parent(self):
+ return self.table
def append_column(self, column):
# make sure all columns are from the same table
# and no column is repeated
@@ -776,18 +815,19 @@ class Index(SchemaItem):
class MetaData(SchemaItem):
"""represents a collection of Tables and their associated schema constructs."""
- def __init__(self, name=None, natural_case=None, **kwargs):
+ def __init__(self, name=None, **kwargs):
# a dictionary that stores Table objects keyed off their name (and possibly schema name)
self.tables = {}
self.name = name
- self.natural_case = natural_case
+ self._set_casing_strategy(name, kwargs)
def is_bound(self):
return False
def clear(self):
self.tables.clear()
def table_iterator(self, reverse=True):
return self._sort_tables(self.tables.values(), reverse=reverse)
-
+ def _get_parent(self):
+ return None
def create_all(self, connectable=None, tables=None, engine=None):
"""create all tables stored in this metadata.