/IBM_DB/ibm_db_django/ibm_db_django/introspection.py
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