1

I have a problem where-by I cannot get Perl DBD::ODBC to use unixODBC after re-compiling and re-installing. It had been previously installed.

I had compiled DBD::ODBC to use the DataDirect ODBC Driver Manager. I now want to recompile it to use unixODBC. However, despite starting with fresh source, configuring (it picks up unixODBC), and then compiling and installing, it seems to be stuck using the DataDirect ODBC Driver Manager. I've gone as far as deleting all the files (I know of) from the Perl module folders, but the problem remains when it's reinstalled.

I'm compiling from source because the server I'm installing on doesn't have an Internet connection, so I haven't been using CPAN.

I'm using unixODBC 1.2.3 with Perl 5.8.4 (it matches the environment) on Solaris 10.

I've removed all I can find:

 1. cd /usr/perl5/site_perl/5.8.4/sun4-solaris-64int/auto/DBD/
 2. sudo rm -R ODBC
 3. cd /usr/perl5/site_perl/5.8.4/sun4-solaris-64int/DBD/
 4. sudo rm -R ODBC
 5. sudo rm ODBC.pm
 6. cd /usr/perl5/5.8.4/man/man3/
 7. sudo rm DBD::ODBC.3
 8. sudo vi /usr/perl5/5.8.4/lib/sun4-solaris-64int/perllocal.pod

I then removed all entries for DBD::ODBC in perllocal.pod.

I can see when I run perl Makefile.PL that it is finding unixODBC.

Looking for odbc_config at /usr/local/unixODBC_sp64/bin/odbc_config
  Found odbc_config (via /usr/local/unixODBC_sp64/bin/odbc_config) version 2.3.2

  odbc_config reports --prefix=/usr/local/unixODBC_sp64
  odbc_config reports --include-prefix=/usr/local/unixODBC_sp64/include
  odbc_config reports --lib-prefix=/usr/local/unixODBC_sp64/lib
  ODBC INC dir set to /usr/local/unixODBC_sp64/include from odbc_config
  ODBC LIB dir set to /usr/local/unixODBC_sp64/lib from odbc_config
Using ODBC HOME /usr/local/unixODBC_sp64

This looks like a unixodbc type of driver manager.
Looking for odbcinst
  odbcinst -j reports:

unixODBC 2.3.2
DRIVERS............: /usr/local/unixODBC_sp64/etc/odbcinst.ini
SYSTEM DATA SOURCES: /usr/local/unixODBC_sp64/etc/odbc.ini
FILE DATA SOURCES..: /usr/local/unixODBC_sp64/etc/ODBCDataSources
USER DATA SOURCES..: /usr/local/unixODBC_sp64/etc/odbc.ini

Here are all environment variables relating to ODBC in the environment on which I'm compiling and installing the module

LD_LIBRARY_PATH=/usr/local/unixODBC_sp64/lib:
LD_LIBRARY_PATH_64=/usr/local/unixODBC_sp64/lib:
PATH=/usr/local/unixODBC_sp64/bin:/usr/sfw/bin:/usr/ccs/bin:/opt/SUNWspro/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/bin
ODBCINI=/usr/local/unixODBC_sp64/etc/odbc.ini
ODBCHOME=/usr/local/unixODBC_sp64

When I run a test I still see an error from the DataDirect driver manager:

DBI connect('lksdjhf','ljkshdf',...) failed: [DataDirect][ODBC lib] System information file not found. Please check the ODBCINI environment variable. (SQL-IM002) at ./test_odbcdb2.pl line 19

Ignore the fact that it can't find the driver, because odbc.ini isn't populated. I'm testing with a junk connection because I want to see this same error message from unixODBC.

The Perl script I'm using for testing is below. It works with the DataDirect driver manager.

#!/usr/bin/perl -w

use DBI;
use DBD::ODBC;
use DBD::DB2::Constants;

print "Enter Data Source Name:";
my $dsn =<STDIN>;
chomp $dsn;
my $data_source = "DBI:ODBC:$dsn";
print "Enter Username:";
my $user =<STDIN>;
print "Enter password:";
my $password =<STDIN>;
chomp $user;
chomp $password;

# Connect to the db2 database using odbc
my $dbh = DBI->connect($data_source, $user, $password, {AutoCommit =>1})
                or die "Can't connect to $data_source: $DBI::errstr";
$stmt = "SELECT current timestamp from sysibm.sysdummy1; ";
$sth = $dbh->prepare($stmt);
$sth->execute();

#associate variable with output columns...

$sth->bind_col(1,\$timestap);
while ($sth->fetch) {
           print "The time is: $timestap\n";
}
$dbh->disconnect;
LokMac
  • 391
  • 2
  • 8
  • 17
  • 1
    what does `./test_odbcdb2.pl line 19` contain? – slayedbylucifer May 12 '14 at 06:36
  • my $dbh = DBI->connect($data_source, $user, $password, {AutoCommit =>1}) or die "Can't connect to $data_source: $DBI::errstr"; – LokMac May 12 '14 at 06:59
  • @slayedbylucifer - I've added the full test Perl script to the question. Thanks. – LokMac May 12 '14 at 07:01
  • In the past, I have used `unixodbc` along with `freetds`. and I would do connectivity test using `tql` and `isql` before moving on to perl. Check one of my answers from another post if it helps you: http://stackoverflow.com/a/21252539/1251660 – slayedbylucifer May 12 '14 at 07:11
  • Thanks @slayedbylucifer, but there is no connectivity issue using `isql` that comes with `unixODBC`. I'm not even getting to the point of connectivity as a result of DBD::ODBC not referencing the correct driver manager. – LokMac May 12 '14 at 08:27
  • I think the problem is **`DBI`** and not `DBD::ODBC`. `DBI` is the one who chooses the Driver. `DBD::ODBC` is **THE** driver. – slayedbylucifer May 12 '14 at 13:46
  • Also, shouldn't `my $data_source = "DBI:ODBC:$dsn";` be `my $data_source = "dbi:ODBC:$dsn";` ? Notice that it's **`dbi`** (in lower case) – slayedbylucifer May 12 '14 at 14:04
  • @slayedbylucifer - I don't think that is the case regarding DBI vs DBD::ODBC. It is at the time of DBD::ODBC configuration that it selects which ODBC driver manager to use. That can be seen in the above example of executing `perl Makefile.PL` where it has logic to identify which ODBC driver manager is installed. – LokMac May 13 '14 at 01:06
  • @slayedbylucifer - The test code works with the DataDirect ODBC driver manager, so there's no problem with the function of the code. The error message shows that it is getting as far as the ODBC driver manager, so I assume that means the problem lies beyond the test code, and in the DBD::ODBC connection to the driver manager? – LokMac May 13 '14 at 01:07

1 Answers1

3

You didn't say if you did a make install at the end of the build but I'll assume you did.

You didn't say if those LD_LIBRARY_xx env vars are just set or exported as well.

Firstly, addressing other comments.

  1. "DBI:ODBC:$dsn" should indeed be "dbi:ODBC:$dsn".
  2. Perl DBI does load the driver based on the string after "dbi:" so "ODBC" loads the DBD::ODBC module.
  3. "It is at the time of DBD::ODBC configuration that it selects which ODBC driver manager to use" is not correct. Configuration only selects the driver manager to compile against. I don't believe a "runpath" instruction to the linker is provided at link time. So you could happily build against unixODBC and run against DD which you seem to be doing.

Find ODBC.so in your Perl tree (it should be in a dir called DBD/ODBC something like /home/martin/perl5/perlbrew/perls/perl-5.19.10/lib/site_perl/5.19.10/x86_64-linux/auto/DBD/ODBC/ODBC.so). Now run "ldd ODBC.so" on it and look to see in the output where the libodbc.so comes from e.g.:

$ ldd ./blib/arch/auto/DBD/ODBC/ODBC.so
        libodbc.so.1 =>  /usr/local/lib/libodbc.so.1
        libdl.so.1 =>    /usr/lib/libdl.so.1
        libthread.so.1 =>        /usr/lib/libthread.so.1
        libc.so.1 =>     /usr/lib/libc.so.1
        /usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1

Here the dynamic linker is resolving the dependency on libodbc.so.1 with /usr/local/lib/libodbc.so.1. You need to tell the dynamic linker to look in your unixODBC lib dir before wherever it is looking now. Using LD_LIBRARY_PATH might not work - especially if you run as root and there are global ways of telling the dynamic liker where to look. Read your ld.so.1 section 1 man page.

bohica
  • 5,932
  • 3
  • 23
  • 28
  • That's a lot of good information coming from the Author himself. Thanks. +1. – slayedbylucifer May 13 '14 at 10:33
  • Sorry I haven't checked this out yet. I've been very busy, and now sick. I'll give this a try in a couple of days and let you know. Thanks for your response. – LokMac May 19 '14 at 14:42
  • Ahh, yes, very interesting. Nothing wrong with LD_LIBRARY_PATH as such, but because ODBC.so is 32-bit and the ODBC driver manager we were using was 64-bit, it was bypassing the drivers from the driver manager and didn't find libodbc.so until it got all the way to the last entry in LD_LIBRARY_PATH which was /usr/lib. – LokMac May 29 '14 at 08:03
  • $ ldd /usr/perl5/site_perl/5.8.4/sun4-solaris-64int/auto/DBD/ODBC/ODBC.so libodbc.so => /usr/local/unixODBC_sp32/lib/libodbc.so libodbc.so (VERS_3.52) => (version not found) libthread.so.1 => /usr/lib/libthread.so.1 libc.so.1 => /usr/lib/libc.so.1 libgcc_s.so.1 => /usr/sfw/lib/libgcc_s.so.1 libm.so.2 => /usr/lib/libm.so.2 /lib/libm/libm_hwcap1.so.2 /platform/sun4v/lib/libc_psr.so.1 – LokMac May 29 '14 at 08:05
  • It's got a different problem if I use the 32-bit driver manager that I'll have to look into, but it looks like you've got me on the right track. Thanks. I'll pass on the results. I think something has changed because now it's not finding the version of libodbc.so that it wants (it did when I tested earlier but something must have changed). It looks like I'm close to a solution with your help, though possibly we now face more complication than we thought with 32-bit vs 64-bit. – LokMac May 29 '14 at 08:06
  • This still doesn't explain how it's getting to the 64-bit DataDirect driver manager though... When I change it back to that, it only finds libodbc.so from /usr/lib, so why is it getting a message from a driver manager in a different folder? – LokMac May 29 '14 at 08:10
  • Ahh, more progress. It turns out that Teradata replaces /usr/lib/libodbc.so with a symlink to its own driver manager! /usr/lib/libodbc.so -> /opt/teradata/client/ODBC_32/lib/libodbc.so. This is definitely not what we want in this case. – LokMac May 29 '14 at 23:51
  • While I haven't got it working because of other problems, you were spot on that this was the problem. It was getting the path from LD_LIBRARY_PATH, BUT it turned out that Teradata also has a bundled DataDirect Driver Manager with it's ODBC driver, and it has created symlinks for all it's ODBC drivers in /usr/lib as part of it's install. It was using the driver found in /usr/lib (Teradata DataDirect) because the version of unixODBC I had installed didn't have the necessary version of libodbc.so. So I just need to find the right version of Perl, or upgrade to the latest DBD::ODBC I think. – LokMac May 30 '14 at 07:19