PageRenderTime 104ms CodeModel.GetById 40ms app.highlight 21ms RepoModel.GetById 39ms app.codeStats 0ms

/IBM_DB/ibm_db_django/ibm_db_django/introspection.py

http://ibm-db.googlecode.com/
Python | 196 lines | 139 code | 15 blank | 42 comment | 38 complexity | d60a7467fdff375ea4ac81cc5b647c08 MD5 | raw file
  1# +--------------------------------------------------------------------------+
  2# |  Licensed Materials - Property of IBM                                    |
  3# |                                                                          |
  4# | (C) Copyright IBM Corporation 2009.                                      |
  5# +--------------------------------------------------------------------------+
  6# | This module complies with Django 1.0 and is                              |
  7# | Licensed under the Apache License, Version 2.0 (the "License");          |
  8# | you may not use this file except in compliance with the License.         |
  9# | You may obtain a copy of the License at                                  |
 10# | http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable |
 11# | law or agreed to in writing, software distributed under the License is   |
 12# | distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
 13# | KIND, either express or implied. See the License for the specific        |
 14# | language governing permissions and limitations under the License.        |
 15# +--------------------------------------------------------------------------+
 16# | Authors: Ambrish Bhargava, Tarun Pasrija, Rahul Priyadarshi              |
 17# +--------------------------------------------------------------------------+
 18
 19import sys
 20from string import upper
 21_IS_JYTHON = sys.platform.startswith( 'java' )
 22
 23if not _IS_JYTHON:
 24    try:    
 25        # Import IBM_DB wrapper ibm_db_dbi
 26        import ibm_db_dbi as Database
 27        #from Database import DatabaseError
 28    except ImportError, e:
 29        raise ImportError( "ibm_db module not found. Install ibm_db module from http://code.google.com/p/ibm-db/. Error: %s" % e )
 30else:
 31    from com.ziclix.python.sql import zxJDBC
 32
 33from django.db.backends import BaseDatabaseIntrospection
 34from django import VERSION as djangoVersion
 35
 36class DatabaseIntrospection( BaseDatabaseIntrospection ):
 37    
 38    """
 39    This is the class where database metadata information can be generated.
 40    """
 41
 42    if not _IS_JYTHON:
 43        if( djangoVersion[0:2] <= ( 1, 1 ) ):
 44            data_types_reverse = {
 45                Database.STRING :           "CharField",
 46                Database.TEXT :             "TextField",
 47                Database.XML :              "XMLField",
 48                Database.NUMBER :           "IntegerField",
 49                Database.BIGINT :           "IntegerField",
 50                Database.FLOAT :            "FloatField",
 51                Database.DECIMAL :          "DecimalField",
 52                Database.DATE :             "DateField",
 53                Database.TIME :             "TimeField",
 54                Database.DATETIME :         "DateTimeField",
 55                Database.BINARY :           "ImageField",
 56            }
 57        else:
 58            data_types_reverse = {
 59                Database.STRING :           "CharField",
 60                Database.TEXT :             "TextField",
 61                Database.XML :              "XMLField",
 62                Database.NUMBER :           "IntegerField",
 63                Database.BIGINT :           "BigIntegerField",
 64                Database.FLOAT :            "FloatField",
 65                Database.DECIMAL :          "DecimalField",
 66                Database.DATE :             "DateField",
 67                Database.TIME :             "TimeField",
 68                Database.DATETIME :         "DateTimeField",
 69                Database.BINARY :           "ImageField",
 70            }
 71    else:
 72        data_types_reverse = {
 73            zxJDBC.CHAR:                "CharField",
 74            zxJDBC.BIGINT:              "BigIntegerField",
 75            zxJDBC.BINARY:              "ImageField",
 76            zxJDBC.BIT:                 "SmallIntegerField",
 77            zxJDBC.BLOB:                "ImageField",
 78            zxJDBC.CLOB:                "TextField",
 79            zxJDBC.DATE:                "DateField",
 80            zxJDBC.DECIMAL:             "DecimalField",
 81            zxJDBC.DOUBLE:              "FloatField",
 82            zxJDBC.FLOAT:               "FloatField",
 83            zxJDBC.INTEGER:             "IntegerField",
 84            zxJDBC.LONGVARCHAR:         "TextField",
 85            zxJDBC.LONGVARBINARY:       "ImageField",
 86            zxJDBC.NUMERIC:             "DecimalField",
 87            zxJDBC.REAL:                "FloatField",
 88            zxJDBC.SMALLINT:            "SmallIntegerField",
 89            zxJDBC.VARCHAR:             "CharField",
 90            zxJDBC.TIMESTAMP:           "DateTimeField",
 91            zxJDBC.TIME:                "TimeField",
 92        }
 93     
 94    # Converting table name to lower case.
 95    def table_name_converter ( self, name ):        
 96        return name.lower()
 97    
 98    # Getting the list of all tables, which are present under current schema.
 99    def get_table_list ( self, cursor ):
100        table_list = []
101        if not _IS_JYTHON:
102            for table in cursor.connection.tables( cursor.connection.get_current_schema() ):
103                table_list.append( table['TABLE_NAME'].lower() )
104        else:
105            cursor.execute( "select current_schema from sysibm.sysdummy1" )
106            schema = cursor.fetchone()[0]
107            # tables(String catalog, String schemaPattern, String tableNamePattern, String[] types) gives a description of tables available in a catalog 
108            cursor.tables( None, schema, None, ( "TABLE", ) )
109            for table in cursor.fetchall():
110                # table[2] is table name
111                table_list.append( table[2].lower() )
112                
113        return table_list
114    
115    # Generating a dictionary for foreign key details, which are present under current schema.
116    def get_relations( self, cursor, table_name ):
117        relations = {}
118        if not _IS_JYTHON:
119            schema = cursor.connection.get_current_schema()
120            for fk in cursor.connection.foreign_keys( True, schema, table_name ):
121                relations[self.__get_col_index( cursor, schema, table_name, fk['FKCOLUMN_NAME'] )] = ( self.__get_col_index( cursor, schema, fk['PKTABLE_NAME'], fk['PKCOLUMN_NAME'] ), fk['PKTABLE_NAME'].lower() )
122        else:
123            cursor.execute( "select current_schema from sysibm.sysdummy1" )
124            schema = cursor.fetchone()[0]
125            # foreign_keys(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) 
126            # gives a description of the foreign key columns in the foreign key table that reference the primary key columns 
127            # of the primary key table (describe how one table imports another's key.) This should normally return a single foreign key/primary key pair 
128            # (most tables only import a foreign key from a table once.) They are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and KEY_SEQ
129            cursor.foreignkeys( None, schema, table_name, None, '%', '%' )
130            for fk in cursor.fetchall():
131                # fk[2] is primary key table name, fk[3] is primary key column name, fk[7] is foreign key column name being exported
132                relations[self.__get_col_index( cursor, schema, table_name, fk[7] )] = ( self.__get_col_index( cursor, schema, fk[2], fk[3] ), fk[3], fk[2] )
133        return relations
134    
135    # Private method. Getting Index position of column by its name
136    def __get_col_index ( self, cursor, schema, table_name, col_name ):
137        if not _IS_JYTHON:
138            for col in cursor.connection.columns( schema, table_name, [col_name] ):
139                return col['ORDINAL_POSITION'] - 1
140        else:
141            cursor.execute( "select current_schema from sysibm.sysdummy1" )
142            schema = cursor.fetchone()[0]
143            # columns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) gives a description of table columns available in the specified catalog
144            cursor.columns( None, schema, table_name, col_name )
145            for col in cursor.fetchall():
146                #col[16] is index of column in table
147                return col[16] - 1
148    
149    # Getting list of indexes associated with the table provided.
150    def get_indexes( self, cursor, table_name ):
151        indexes = {}
152        if not _IS_JYTHON:
153            schema = cursor.connection.get_current_schema()
154            for index in cursor.connection.indexes( True, schema, table_name ):
155                temp = {}
156                if ( index['NON_UNIQUE'] ):
157                    temp['unique'] = False
158                else:
159                    temp['unique'] = True
160                temp['primary_key'] = False
161                indexes[index['COLUMN_NAME'].lower()] = temp
162            
163            for index in cursor.connection.primary_keys( True, schema, table_name ):
164                indexes[index['COLUMN_NAME'].lower()]['primary_key'] = True
165        else:
166            cursor.execute( "select current_schema from sysibm.sysdummy1" )
167            schema = cursor.fetchone()[0]
168            # statistics(String catalog, String schema, String table, boolean unique, boolean approximate) returns a description of a table's indices and statistics. 
169            cursor.statistics( None, schema, table_name, 0, 0 )
170            for index in cursor.fetchall():
171                temp = {}
172                # index[3] indicate non-uniqueness of column
173                if ( index[3] != None ):
174                    if ( index[3] ) == 1:
175                        temp['unique'] = False
176                    else:
177                        temp['unique'] = True
178                    temp['primary_key'] = False
179                    # index[8] is column name
180                    indexes[index[8].lower()] = temp
181            
182            # primarykeys(String catalog, String schema, String table) gives a description of a table's primary key columns
183            cursor.primarykeys( None, schema, table_name )
184            for index in cursor.fetchall():
185                #index[3] is column name
186                indexes[index[3].lower()]['primary_key'] = True
187        return indexes
188    
189    # Getting the description of the table.
190    def get_table_description( self, cursor, table_name ):
191        qn = self.connection.ops.quote_name
192        cursor.execute( "SELECT * FROM %s FETCH FIRST 1 ROWS ONLY" % qn( table_name ) )   
193        description = []
194        for desc in cursor.description:
195            description.append( [ desc[0].lower(), ] + desc[1:] )
196        return description