> Hi All
>
> I am using Sqlalchemy 0.6.6 + cx_oracle5.0.3+python 2.6.4 and
> oracle 10g from linux.
>
> when I tried the sqlalchemy autoload feature
>
> tbl=Table('autoload_test', meta,
> autoload=True,autoload_with=engine, schema=None)
>
> Here I am getting tbl.columns.keys() are all lower case even if
> my column names are in upper case in DB . I checked the issue and
> found the reason
>
> in get_columns method (sqlalchemy/dialects/oracle/base.py)
> after fetching the column names in the loop before assigning the
> column name to colname variable normalize_name(sqlalchemy/dialects/
> oracle/base.py) method is calling and finally the colname varaiable
> will set as a value of name key and finally the dict will append to a
> list in the loop.
SQLAlchemy considers all lower case names to indicate a "case insensitive" name, whereas Oracle has the opposite behavior - it represents case insensitive names as all uppercase. SQLAlchemy's behavior in this regard is described at http://www.sqlalchemy.org/docs/dialects/oracle.html#identifier-casing . The "normalize_name" method you've found is part of the implementation of this approach.
>
> Here the problem is lc_value!=value checking ,suppose my column name
> is 'FIRST_NAME'
If your column is named "FIRST_NAME" in the Oracle database, and was named without quotes, the identifier is case insensitive. Any casing will match it. If you've named it "FIRST_NAME" and you did actually use quotes in the CREATE TABLE statement, Oracle still considers that name to be equivalent to "first_name", as long as quoting isn't used - because all uppercase is case insensitive in Oracle. See note #8 at http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements008.htm (I also tried here to confirm).
> I am getting table column names in upper case (ie how they are in
> DB, here I am not using any quoted column names') . . Now SQLServer
> +SqlAlchemy +autoload give upper case column names in upper case but
because SQL Server uses lowercase names to indicate "case insensitive". Oracle does the opposite.
> when connecting with oracle upper case column names will be converted
> to lower case.Anybody have an idea why requires_quotes method is
> called like this?
Because SQLAlchemy is normalizing the differences in casing conventions to work across all databases with no changes in the declared Python metadata needed.
>
> HI Michael ,
> Thanks for your reply,this is my table creation query without any
> quoted variables
>
> CREATE TABLE AUTOLOAD_TEST
> (
> ID INTEGER
> , FIRST_NAME VARCHAR(20)
> );
>
> this is my connect_sqlalchemy.py script
> ++++++++++++++++++++++++++++++++++++++++++
>
> from sqlalchemy import MetaData,create_engine,Table
> engine = create_engine("oracle+cx_oracle://anoop:asdfgh@xe" )
> meta = MetaData(engine)
> tbl_autoload_test=Table('autoload_test', meta, autoload=True,
> autoload_with=engine, schema=None)
> print tbl_autoload_test.columns.keys()
> ++++++++++++++++++++++++++++++++++++++++++
>
> When I run this script
> (myenv)anoop@AGLAP:~/Example/sqlalchemy$ python connect_sqlalchemy.py
> [u'id', u'first_name'] #Here I got column names in lower case
>
>
> if name.upper() == name and \
> not
> self.identifier_preparer._requires_quotes(name.lower()):
> return name.lower()
> else:
> return name
> if name.upper() == name and \
> not self.identifier_preparer._requires_quotes(name): #
> this is my change not converted into lower when calling
> return name.lower()
> else:
> return name
>
> [u'ID', u'FIRST_NAME'] # Here output is in Capital letters not
>
> Did you got my point ?
I'm assuming what you're looking for here is columns.keys() to be converted to uppercase. To be honest, to suit your use case, you should just say my_keys = [k.upper() for k in table.columns.keys() if k.lower() == k]. Because you shouldn't be thinking of those names as upper case *or* lowercase - they are case insensitive. SQLA uses all lower case to indicate case insensitive, Oracle uses all uppercase. You can emit the statement "select FIRST_NAME from autoload_test" or "select first_name from autoload_test" on your oracle database and you get the same result.
With your change, we basically treat Oracle names as UPPERCASE for case insensitive, the way Oracle itself does. Which is the reverse of the usage contract that SQLAlchemy provides for all other backends. Tables now have to be referenced as table.c.SOME_COLUMN, mapped classes will look like MyClass.FIRST_NAME, etc. If I make your change, symmetrically or not versus denormalize_name, there are dozens of test failures, illustrated here: http://paste.pocoo.org/show/368744/ . All the tests in test_reflection are normally fully cross-platform compatible. If we make an arbitrary reversal of SQLAlchemy's case insensitive convention in the case of Oracle, virtually all tests regarding reflection do not act as expected.