diff options
Diffstat (limited to 'lib/sqlalchemy/schema.py')
-rw-r--r-- | lib/sqlalchemy/schema.py | 94 |
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. |