1 package DBUtil; 2 # 3 # $RCSfile: DBUtil.pm,v $ 4 # $Date: 2008/04/25 00:00:45 $ 5 # $Revision: 1.19 $ 6 # 7 # Author: Manish Sud <msud@san.rr.com> 8 # 9 # Copyright (C) 2004-2008 Manish Sud. All rights reserved. 10 # 11 # This file is part of MayaChemTools. 12 # 13 # MayaChemTools is free software; you can redistribute it and/or modify it under 14 # the terms of the GNU Lesser General Public License as published by the Free 15 # Software Foundation; either version 3 of the License, or (at your option) any 16 # later version. 17 # 18 # MayaChemTools is distributed in the hope that it will be useful, but without 19 # any warranty; without even the implied warranty of merchantability of fitness 20 # for a particular purpose. See the GNU Lesser General Public License for more 21 # details. 22 # 23 # You should have received a copy of the GNU Lesser General Public License 24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or 25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, 26 # Boston, MA, 02111-1307, USA. 27 # 28 use 5.006; 29 use strict; 30 use Exporter; 31 use Carp; 32 use DBI; 33 use TextUtil; 34 35 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 36 37 $VERSION = '1.00'; 38 @ISA = qw(Exporter); 39 @EXPORT = qw(DBConnect DBDisconnect DBFetchSchemaTableNames DBSetupDescribeSQL DBSetupSelectSQL DBSQLToTextFile); 40 @EXPORT_OK = qw(); 41 %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]); 42 43 # Connect to a specified database... 44 sub DBConnect { 45 my($DBDriver, $DBName, $DBHost, $DBUser, $DBPassword) = @_; 46 my($DBHandle, $DataSource); 47 48 if ($DBDriver eq "Oracle") { 49 $DataSource = ($DBName && $DBHost) ? (qq(DBI:$DBDriver:sid=$DBName;host=$DBHost)) : (qq(DBI:$DBDriver:$DBHost)); 50 } 51 else { 52 $DataSource = qq(DBI:$DBDriver:database=$DBName); 53 if ($DBHost) { 54 $DataSource .= qq(;host=$DBHost); 55 } 56 } 57 58 # Don't raise the error; otherwise, DBI functions termiates on encountering an error. 59 # All terminations decisions are made outside of DBI functions... 60 $DBHandle = DBI->connect($DataSource, $DBUser, $DBPassword, { RaiseError => 0, AutoCommit => 0 }) or croak "Couldn't connect to database..."; 61 62 return $DBHandle; 63 } 64 65 # Disconnect from a database... 66 sub DBDisconnect { 67 my($DBHandle) = @_; 68 69 $DBHandle->disconnect or carp "Couldn't disconnect from a database..."; 70 } 71 72 # Fetch all table name for a database schema... 73 sub DBFetchSchemaTableNames { 74 my($DBDriver, $DBHandle, $SchemaName) = @_; 75 my(@SchemaTableNames, $SQL, $SQLHandle); 76 77 @SchemaTableNames = (); 78 79 $SchemaName = (defined $SchemaName && length $SchemaName) ? uc $SchemaName : ""; 80 81 if ($DBDriver eq "mysql") { 82 # Switch schemas... 83 $SQL = qq(USE $SchemaName); 84 $SQLHandle = $DBHandle->prepare($SQL) or return @SchemaTableNames; 85 $SQLHandle->execute or return @SchemaTableNames; 86 $SQLHandle->finish or return @SchemaTableNames; 87 88 # Setup to fetch table names... 89 $SQL = qq(SHOW TABLES); 90 } 91 elsif ($DBDriver eq "Oracle") { 92 $SQL = qq(SELECT SEGMENT_NAME FROM DBA_SEGMENTS WHERE OWNER = '$SchemaName' AND SEGMENT_TYPE = 'TABLE' ORDER BY SEGMENT_NAME); 93 } 94 $SQLHandle = $DBHandle->prepare($SQL) or return @SchemaTableNames; 95 $SQLHandle->execute or return @SchemaTableNames; 96 97 my(@RowValues, $TableName); 98 while (@RowValues = $SQLHandle->fetchrow_array) { 99 $TableName = uc $RowValues[0]; 100 if (defined $TableName && length $TableName) { 101 push @SchemaTableNames, $TableName; 102 } 103 } 104 $SQLHandle->finish or return @SchemaTableNames; 105 106 return @SchemaTableNames; 107 } 108 109 # Setup describe SQL statement... 110 sub DBSetupDescribeSQL { 111 my($DBDriver, $TableName, $SchemaName); 112 my($DescribeSQL); 113 114 $DBDriver = ""; $TableName = ""; $SchemaName = ""; 115 if (@_ == 3) { 116 ($DBDriver, $TableName, $SchemaName) = @_; 117 } 118 else { 119 ($DBDriver, $TableName) = @_; 120 } 121 $TableName = (defined $TableName && length $TableName) ? uc $TableName : ""; 122 $SchemaName = (defined $SchemaName && length $SchemaName) ? uc $SchemaName : ""; 123 124 $DescribeSQL = ($SchemaName) ? ("DESCRIBE " . "$SchemaName" . ".$TableName") : "DESCRIBE $TableName"; 125 126 if ($DBDriver eq "Oracle") { 127 $DescribeSQL = qq(SELECT COLUMN_NAME "Column_Name", DECODE(NULLABLE, 'N','Not Null','Y','Null') "Null", DATA_TYPE "Data_Type", DATA_LENGTH "Data_Length", DATA_PRECISION "Data_Precision" FROM DBA_TAB_COLUMNS WHERE TABLE_NAME = '$TableName'); 128 if ($SchemaName) { 129 $DescribeSQL .= qq( AND OWNER = '$SchemaName'); 130 } 131 $DescribeSQL .= qq( ORDER BY COLUMN_ID); 132 } 133 134 return $DescribeSQL; 135 } 136 137 # Setup describe SQL statement... 138 sub DBSetupSelectSQL { 139 my($DBDriver, $TableName, $SchemaName); 140 my($SelectSQL); 141 142 $DBDriver = ""; $TableName = ""; $SchemaName = ""; 143 if (@_ == 3) { 144 ($DBDriver, $TableName, $SchemaName) = @_; 145 } 146 else { 147 ($DBDriver, $TableName) = @_; 148 } 149 $TableName = (defined $TableName && length $TableName) ? uc $TableName : ""; 150 $SchemaName = (defined $SchemaName && length $SchemaName) ? uc $SchemaName : ""; 151 152 $SelectSQL = ($SchemaName) ? ("SELECT * FROM " . "$SchemaName" . ".$TableName") : "SELECT * FROM $TableName"; 153 154 return $SelectSQL; 155 } 156 157 # Prepare and execute a SQL statement and write out results into 158 # a text file. 159 sub DBSQLToTextFile { 160 my($DBHandle, $SQL, $TextFile, $OutDelim, $OutQuote, $ExportDataLabels, $ExportLOBs, $ReplaceNullStr); 161 my($SQLHandle, $Status); 162 163 $Status = 1; 164 $ExportDataLabels = 1; 165 $ExportLOBs = 0; 166 $ReplaceNullStr = ""; 167 if (@_ == 8) { 168 ($DBHandle, $SQL, $TextFile, $OutDelim, $OutQuote, $ExportDataLabels, $ExportLOBs, $ReplaceNullStr) = @_; 169 } 170 elsif (@_ == 7) { 171 ($DBHandle, $SQL, $TextFile, $OutDelim, $OutQuote, $ExportDataLabels, $ExportLOBs) = @_; 172 } 173 elsif (@_ == 6) { 174 ($DBHandle, $SQL, $TextFile, $OutDelim, $OutQuote, $ExportDataLabels) = @_; 175 } 176 else { 177 ($DBHandle, $SQL, $TextFile, $OutDelim, $OutQuote) = @_; 178 } 179 180 # Execute SQL statement... 181 $SQLHandle = $DBHandle->prepare($SQL) or return $Status; 182 $SQLHandle->execute() or return $Status; 183 184 my($FieldsNum, @FieldNames, @RowValues, @ColNumsToExport, @ColLabels, $ColNum, $ColLabelsLine, @Values, $Value, $ValuesLine); 185 186 $Status = 0; 187 # Figure out which column numbers need to be exported... 188 $FieldsNum = $SQLHandle->{NUM_OF_FIELDS}; 189 @FieldNames = @{$SQLHandle->{NAME}}; 190 @ColNumsToExport = (); 191 if ($ExportLOBs) { 192 @ColNumsToExport = (0 .. $#FieldNames); 193 } 194 else { 195 my(@FieldTypes, @FieldTypeNames, $Type, $TypeName); 196 @FieldTypes = @{$SQLHandle->{TYPE}}; 197 @FieldTypeNames = map { scalar $DBHandle->type_info($_)->{TYPE_NAME} } @FieldTypes; 198 for $ColNum (0 .. $#FieldNames) { 199 if ($FieldTypeNames[$ColNum] !~ /lob/i ) { 200 push @ColNumsToExport, $ColNum; 201 } 202 } 203 } 204 205 if ($ExportDataLabels) { 206 # Print out column labels... 207 @ColLabels = (); 208 for $ColNum (@ColNumsToExport) { 209 push @ColLabels, $FieldNames[$ColNum]; 210 } 211 $ColLabelsLine = JoinWords(\@ColLabels, $OutDelim, $OutQuote); 212 print $TextFile "$ColLabelsLine\n"; 213 } 214 # Print out row values... 215 while (@RowValues = $SQLHandle->fetchrow_array) { 216 @Values = (); 217 for $ColNum (@ColNumsToExport) { 218 if (defined($RowValues[$ColNum]) && length($RowValues[$ColNum])) { 219 $Value = $RowValues[$ColNum]; 220 } 221 else { 222 $Value = $ReplaceNullStr ? $ReplaceNullStr : ""; 223 } 224 push @Values, $Value; 225 } 226 $ValuesLine = JoinWords(\@Values, $OutDelim, $OutQuote); 227 print $TextFile "$ValuesLine\n"; 228 } 229 $SQLHandle->finish or return $Status; 230 $Status = 0; 231 232 return $Status; 233 } 234