]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- case_sensitive=(True|False) setting removed from schema items, since
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 11 Aug 2007 14:03:23 +0000 (14:03 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 11 Aug 2007 14:03:23 +0000 (14:03 +0000)
    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).

CHANGES
lib/sqlalchemy/ansisql.py
lib/sqlalchemy/databases/informix.py
lib/sqlalchemy/schema.py
lib/sqlalchemy/sql.py
test/sql/quote.py

diff --git a/CHANGES b/CHANGES
index 068b0c96d634b8ed86c86d7eac501178d525c0fa..0fc09c6835c95147389891956874d80862460cb4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
   - 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".
-    
+  
+  - 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).
+        
   - transactions:
     - added context manager (with statement) support for transactions
     - added support for two phase commit, works with mysql and postgres so far.
     - table reflection can now be performed in as little as one round-trip
     - ANSI and ANSI_QUOTES sql modes are now supported
     - indexes are now reflected
+    
 - postgres
   - Added PGArray datatype for using postgres array datatypes
 
index 0efaf86575d39338ef8e3dfde25fe75e100c403d..14bae1d1704767c7b06d3d9592d89c2152b97731 100644 (file)
@@ -1013,35 +1013,34 @@ class ANSIIdentifierPreparer(object):
     def _illegal_initial_characters(self):
         return ILLEGAL_INITIAL_CHARACTERS
 
-    def _requires_quotes(self, value, case_sensitive):
+    def _requires_quotes(self, value):
         """Return True if the given identifier requires quoting."""
         return \
             value in self._reserved_words() \
             or (value[0] in self._illegal_initial_characters()) \
             or bool(len([x for x in unicode(value) if x not in self._legal_characters()])) \
-            or (case_sensitive and value.lower() != value)
+            or (value.lower() != value)
 
     def __generic_obj_format(self, obj, ident):
         if getattr(obj, 'quote', False):
             return self.quote_identifier(ident)
         if self.dialect.cache_identifiers:
-            case_sens = getattr(obj, 'case_sensitive', None)
             try:
-                return self.__strings[(ident, case_sens)]
+                return self.__strings[ident]
             except KeyError:
-                if self._requires_quotes(ident, getattr(obj, 'case_sensitive', ident == ident.lower())):
-                    self.__strings[(ident, case_sens)] = self.quote_identifier(ident)
+                if self._requires_quotes(ident):
+                    self.__strings[ident] = self.quote_identifier(ident)
                 else:
-                    self.__strings[(ident, case_sens)] = ident
-                return self.__strings[(ident, case_sens)]
+                    self.__strings[ident] = ident
+                return self.__strings[ident]
         else:
-            if self._requires_quotes(ident, getattr(obj, 'case_sensitive', ident == ident.lower())):
+            if self._requires_quotes(ident):
                 return self.quote_identifier(ident)
             else:
                 return ident
 
     def should_quote(self, object):
-        return object.quote or self._requires_quotes(object.name, object.case_sensitive)
+        return object.quote or self._requires_quotes(object.name)
 
     def format_sequence(self, sequence):
         return self.__generic_obj_format(sequence, sequence.name)
index e98a5467e309e6c8d81db3572b73ea7f26728487..a3ef999161bf99490c5e81fc68709ba83258fb4b 100644 (file)
@@ -499,7 +499,7 @@ class InfoIdentifierPreparer(ansisql.ANSIIdentifierPreparer):
     def _fold_identifier_case(self, value):
         return value.lower()
     
-    def _requires_quotes(self, value, case_sensitive):
+    def _requires_quotes(self, value):
         return False
 
 class InfoSchemaDroper(ansisql.ANSISchemaDropper):
index d83eaab5880d2df53156b51db06a796447974756..b28eb642b66247b41eb1567b4e923a75d83bc7d5 100644 (file)
@@ -74,53 +74,6 @@ class SchemaItem(object):
             m = self._derived_metadata()
             return m and m.bind or None
 
-    def _set_casing_strategy(self, kwargs, keyname='case_sensitive'):
-        """Set the "case_sensitive" argument sent via keywords to the item's constructor.
-
-        For the purposes of Table's 'schema' property, the name of the
-        variable is optionally configurable.
-        """
-        setattr(self, '_%s_setting' % keyname, kwargs.pop(keyname, None))
-
-    def _determine_case_sensitive(self, keyname='case_sensitive'):
-        """Determine the `case_sensitive` value for this item.
-
-        For the purposes of Table's `schema` property, the name of the
-        variable is optionally configurable.
-
-        A local non-None value overrides all others.  After that, the
-        parent item (i.e. ``Column`` for a ``Sequence``, ``Table`` for
-        a ``Column``, ``MetaData`` for a ``Table``) is searched for a
-        non-None setting, traversing each parent until none are found.
-        finally, case_sensitive is set to True as a default.
-        """
-
-        local = getattr(self, '_%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, '_case_sensitive_setting', None)
-                if parentval is not None:
-                    return parentval
-        return True
-
-    def _get_case_sensitive(self):
-        """late-compile the 'case-sensitive' setting when first accessed.
-        
-        typically the SchemaItem will be assembled into its final structure
-        of other SchemaItems at this point, whereby it can attain this setting 
-        from its containing SchemaItem if not defined locally.
-        """
-        
-        try:
-            return self.__case_sensitive
-        except AttributeError:
-            self.__case_sensitive = self._determine_case_sensitive()
-            return self.__case_sensitive
-    case_sensitive = property(_get_case_sensitive)
 
     metadata = property(lambda s:s._derived_metadata())
     bind = property(lambda s:s._get_bind())
@@ -270,13 +223,6 @@ class Table(SchemaItem, sql.TableClause):
             the database. This flag overrides all other quoting
             behavior.
 
-          case_sensitive
-            Defaults to True: indicates quoting should be used if the
-            identifier contains mixed case.
-
-          case_sensitive_schema
-            Defaults to True: indicates quoting should be used if the
-            identifier contains mixed case.
         """
         super(Table, self).__init__(name)
         self._metadata = metadata
@@ -294,9 +240,6 @@ class Table(SchemaItem, sql.TableClause):
             self.fullname = self.name
         self.owner = kwargs.pop('owner', None)
 
-        self._set_casing_strategy(kwargs)
-        self._set_casing_strategy(kwargs, keyname='case_sensitive_schema')
-
         if len([k for k in kwargs if not re.match(r'^(?:%s)_' % '|'.join(databases.__all__), k)]):
             raise TypeError("Invalid argument(s) for Table: %s" % repr(kwargs.keys()))
 
@@ -310,14 +253,6 @@ class Table(SchemaItem, sql.TableClause):
         # implement it differently
         pass
 
-    def _get_case_sensitive_schema(self):
-        try:
-            return getattr(self, '_case_sensitive_schema')
-        except AttributeError:
-            setattr(self, '_case_sensitive_schema', self._determine_case_sensitive(keyname='case_sensitive_schema'))
-            return getattr(self, '_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)
@@ -505,9 +440,6 @@ class Column(SchemaItem, sql._ColumnClause):
             as dialects can auto-detect conditions where quoting is
             required.
 
-          case_sensitive
-            Defaults to True: indicates quoting should be used if the
-            identifier contains mixed case.
         """
 
         super(Column, self).__init__(name, None, type_)
@@ -520,7 +452,6 @@ class Column(SchemaItem, sql._ColumnClause):
         self.index = kwargs.pop('index', None)
         self.unique = kwargs.pop('unique', None)
         self.quote = kwargs.pop('quote', False)
-        self._set_casing_strategy(kwargs)
         self.onupdate = kwargs.pop('onupdate', None)
         self.autoincrement = kwargs.pop('autoincrement', True)
         self.constraints = util.Set()
@@ -616,7 +547,7 @@ class Column(SchemaItem, sql._ColumnClause):
         This is used in ``Table.tometadata``.
         """
 
-        return Column(self.name, self.type, self.default, key = self.key, primary_key = self.primary_key, nullable = self.nullable, _is_oid = self._is_oid, case_sensitive=self._case_sensitive_setting, quote=self.quote, index=self.index, *[c.copy() for c in self.constraints])
+        return Column(self.name, self.type, self.default, key = self.key, primary_key = self.primary_key, nullable = self.nullable, _is_oid = self._is_oid, quote=self.quote, index=self.index, *[c.copy() for c in self.constraints])
 
     def _make_proxy(self, selectable, name = None):
         """Create a *proxy* for this column.
@@ -639,13 +570,6 @@ class Column(SchemaItem, sql._ColumnClause):
         return c
 
 
-    def _case_sens(self):
-        """Redirect the `case_sensitive` accessor to use the ultimate
-        parent column which created this one."""
-
-        return self.__originating_column._get_case_sensitive()
-    case_sensitive = property(_case_sens, lambda s,v:None)
-
     def get_children(self, schema_visitor=False, **kwargs):
         if schema_visitor:
             return [x for x in (self.default, self.onupdate) if x is not None] + \
@@ -852,7 +776,6 @@ class Sequence(DefaultGenerator):
         self.increment = increment
         self.optional=optional
         self.quote = quote
-        self._set_casing_strategy(kwargs)
 
     def __repr__(self):
         return "Sequence(%s)" % ', '.join(
@@ -1109,7 +1032,7 @@ class MetaData(SchemaItem):
 
     __visit_name__ = 'metadata'
     
-    def __init__(self, bind=None, reflect=False, case_sensitive=None):
+    def __init__(self, bind=None, reflect=False):
         """Create a new MetaData object.
             
         bind
@@ -1123,13 +1046,9 @@ class MetaData(SchemaItem):
           set.  For finer control over loaded tables, use the ``reflect``
           method of ``MetaData``.
 
-        case_sensitive
-          A default case sensitive setting for all contained objects.
-          Defaults to sensitive.
         """        
 
         self.tables = {}
-        self._set_casing_strategy({'case_sensitive': case_sensitive})
         self.bind = bind
         if reflect:
             if not bind:
@@ -1144,12 +1063,10 @@ class MetaData(SchemaItem):
         return key in self.tables
         
     def __getstate__(self):
-        return {'tables': self.tables,
-                'casesensitive': self._case_sensitive_setting}
+        return {'tables': self.tables}
 
     def __setstate__(self, state):
         self.tables = state['tables']
-        self._case_sensitive_setting = state['casesensitive']
         self._bind = None
         
     def is_bound(self):
index ce9ee697189520d6dc9fbf0206b77bbb04d6eff5..5524cdc0568728afb58902de6696572f305ad1da 100644 (file)
@@ -2577,7 +2577,6 @@ class Alias(FromClause):
             alias = '{ANON %d %s}' % (id(self), alias or 'anon')
         self.name = alias
         self.encodedname = alias.encode('ascii', 'backslashreplace')
-        self.case_sensitive = getattr(baseselectable, "case_sensitive", True)
 
     def is_derived_from(self, fromclause):
         x = self.selectable
@@ -2697,7 +2696,6 @@ class _Label(ColumnElement):
         self.name = name or "{ANON %d %s}" % (id(self), getattr(obj, 'name', 'anon'))
 
         self.obj = obj.self_group(against=Operators.as_)
-        self.case_sensitive = getattr(obj, "case_sensitive", True)
         self.type = sqltypes.to_instance(type_ or getattr(obj, 'type', None))
 
     key = property(lambda s: s.name)
@@ -2743,11 +2741,6 @@ class _ColumnClause(ColumnElement):
         ``TypeEngine`` object which can associate this ``_ColumnClause`` 
         with a type.
       
-      case_sensitive
-        defines whether identifier quoting rules will be applied to the
-        generated text of this ``_ColumnClause`` so that it is identified in
-        a case-sensitive manner.
-      
       is_literal
         if True, the ``_ColumnClause`` is assumed to be an exact expression
         that will be delivered to the output with no quoting rules applied
@@ -2756,7 +2749,7 @@ class _ColumnClause(ColumnElement):
     
     """
 
-    def __init__(self, text, selectable=None, type_=None, _is_oid=False, case_sensitive=True, is_literal=False):
+    def __init__(self, text, selectable=None, type_=None, _is_oid=False, is_literal=False):
         self.key = self.name = text
         self.encodedname = isinstance(self.name, unicode) and self.name.encode('ascii', 'backslashreplace') or self.name
         self.table = selectable
@@ -2764,7 +2757,6 @@ class _ColumnClause(ColumnElement):
         self._is_oid = _is_oid
         self._distance = 0
         self.__label = None
-        self.case_sensitive = case_sensitive
         self.is_literal = is_literal
     
     def _clone(self):
index 9791bf9467f7a6d977e397752c754f22fd2fa4cb..f36b8921001a10479bc8d38c7126f7078fc1ae81 100644 (file)
@@ -67,18 +67,6 @@ class QuoteTest(PersistTest):
         print res2
         assert(res2==[(1,2,3),(2,2,3),(4,3,2)])
     
-    def testcascade(self):
-        lcmetadata = MetaData(case_sensitive=False)
-        t1 = Table('SomeTable', lcmetadata, 
-            Column('UcCol', Integer),
-            Column('normalcol', String))
-        t2 = Table('othertable', lcmetadata,
-            Column('UcCol', Integer),
-            Column('normalcol', String, ForeignKey('SomeTable.normalcol')))
-        assert lcmetadata.case_sensitive is False
-        assert t1.c.UcCol.case_sensitive is False
-        assert t2.c.normalcol.case_sensitive is False
-   
     @testing.unsupported('oracle') 
     def testlabels(self):
         """test the quoting of labels.
@@ -108,37 +96,6 @@ class QuoteTest(PersistTest):
         x = x.select()
         assert str(x) == '''SELECT "SomeLabel" \nFROM (SELECT 'FooCol' AS "SomeLabel" \nFROM "ImATable")'''
    
-    # oracle doesn't support non-case-sensitive until ticket #726 is fixed 
-    @testing.unsupported('oracle')    
-    def testlabelsnocase(self):
-        metadata = MetaData()
-        table1 = Table('SomeCase1', metadata,
-            Column('lowercase', Integer, primary_key=True),
-            Column('UPPERCASE', Integer),
-            Column('MixedCase', Integer))
-        table2 = Table('SomeCase2', metadata,
-            Column('id', Integer, primary_key=True, key='d123'),
-            Column('col2', Integer, key='u123'),
-            Column('MixedCase', Integer))
-        
-        # first test case sensitive tables migrating via tometadata
-        meta = MetaData(testbase.db, case_sensitive=False)
-        lc_table1 = table1.tometadata(meta)
-        lc_table2 = table2.tometadata(meta)
-        assert lc_table1.case_sensitive is False
-        assert lc_table1.c.UPPERCASE.case_sensitive is False
-        s = lc_table1.select()
-        assert hasattr(s.c.UPPERCASE, "case_sensitive")
-        assert s.c.UPPERCASE.case_sensitive is False
-        
-        # now, the aliases etc. should be case-insensitive.  PG will screw up if this doesnt work.
-        # also, if this test is run in the context of the other tests, we also test that the dialect properly
-        # caches identifiers with "case_sensitive" and "not case_sensitive" separately.
-        meta.create_all()
-        try:
-            x = lc_table1.select(distinct=True).alias("lala").select().scalar()
-        finally:
-            meta.drop_all()
 
 class PreparerTest(PersistTest):
     """Test the db-agnostic quoting services of ANSIIdentifierPreparer."""