Showing posts with label ODBC. Show all posts
Showing posts with label ODBC. Show all posts

Tuesday, September 2, 2014

Enabling odbc support in perl

Enabling ODBC support in Perl with Perl DBI and DBD::ODBC

This document describes how to build Perl DBI, add the DBD::ODBC module and use an ODBC driver provided by Easysoft in your Perl scripts.

Contents

1.0 Introduction

Easysoft ODBC drivers have been proven with Perl DBI-1.02 - DBI-1.50 and DBD-ODBC 0.20-1.13 although they may work with other versions.
If you are working on OpenVMS please see separate OpenVMS notes later in this file.

2.0 How does ODBC work in Perl

To use an ODBC driver in Perl you generally use the following components:
  1. DBI module - the DBI is a database interface module for Perl
  2. a database driver such as DBD::ODBC which is a perl module the DBI loads. DBD::ODBC is the ODBC Driver for DBI.
  3. an ODBC driver manager such as unixODBC which comes with all Easysoft's UNIX ODBC drivers. You can also use iODBC but Easysoft recommend unixODBC.
  4. an ODBC driver. Easysoft provide a number of UNIX and Windows ODBC drivers at easysoft.com
To use ODBC in Perl you write a perl script which contains use DBI; and call the DBI->connect method with a data_source. DBI's data sources are in the form "dbi:DRIVER" where DRIVER; is the DBI driver which is to be used so for DBD::ODBC you use "dbi:ODBC" and DBI will load the DBD::ODBC module for you.
You build DBD::ODBC with a dependency on an ODBC driver manager such as unixODBC, so when DBI loads the DBD::ODBC Perl module your ODBC driver manager will be loaded too.
ODBC needs an ODBC data source to work with so your DBI->connect call becomes 'dbi:ODBC:ODBC_DSN' where ODBC_DSN is an ODBC data source generally defined in an odbc.ini file your driver manager is using. At this point, the ODBC driver manager will see a SQLDriverConnect or SQLConnect (ODBC APIs) call containing the ODBC data source, it will locate that DSN, lookup the ODBC driver supporting that DSN and load the ODBC driver. The ODBC driver will connect to your database engine then you can use DBI methods.

3.0 What you need to do before attempting to use an ODBC driver in Perl

  1. Make sure you have tested your Perl installation. If you built Perl yourself run the Perl tests.
  2. Make sure you have the minimum requirements of Perl DBI - see the README file that comes with DBI. For DBI 1.43 you need a minimum of Perl 5.6.
    You can download the DBI module from
    http://www.cpan.org/modules/by-module/DBI
    or
    http://search.cpan.org/search?query=DBI
    Read the README that comes with DBI.
  3. Make sure have the minimum requirement of Perl DBD::ODBC - see the README file that comes with DBD::ODBC. For DBD::ODBC 1.10 you need at least DBI 1.201.
    You can download the DBD::ODBC module from
    http://www.cpan.org/modules/by-module/DBD
    or
    http://search.cpan.org/search?query=DBD::ODBC
    Read the README that comes with DBD::ODBC.
Now verify that your ODBC driver is installed and working:
All Easysoft ODBC drivers for UNIX come with the unixODBC driver manager and we strongly recommend you use the unixODBC driver manager with Perl..
  1. Locate the unixODBC driver manager:
    • If you installed unixODBC as part of your Easysoft installation it will be in /usr/local/easysoft/unixODBC. unixODBC programs will be in /usr/local/easysoft/unixODBC/bin.
    • If you built unixODBC yourself it will be in /usr/local (by default) or wherever you set --prefix to. unixODBC programs will be in /usr/local/bin or prefix/bin.
    • if you installed unixODBC as part of a RPM or package it will be in various places but the unixODBC programs should already be on your path (probably /usr/bin).
    You will know if you have the correct path if you can find unixODBC's odbcinst program. In the rest of this section the path to unixODBC programs is called UNIXODBCBIN.
  2. Locate where unixODBC is storing the installed ODBC drivers and SYSTEM DSNs:
    UNIXODBCBIN/odbcinst -j
        
    unixODBC 2.2.3
    DRIVERS............: /etc/odbcinst.ini
    SYSTEM DATA SOURCES: /etc/odbc.ini
    USER DATA SOURCES..: /home/person/.odbc.ini
    In this case /etc/odbcinst.ini is where unixODBC stores a list of the installed ODBC drivers and /etc/odbc.ini contains the SYSTEM DSNs.
    The odbcinst.ini file should already contain an entry for the Easysoft ODBC driver you have installed. e.g. for OOB it will look similar to this:
    [OOB]
    Description             = Easysoft ODBC-ODBC Bridge
    Driver          = /usr/local/easysoft/oob/client/libesoobclient.so
    Setup           = /usr/local/easysoft/oob/client/libesoobsetup.so
    FileUsage               = 1
    If you haven't got an ODBC driver in odbcinst.ini you need to check the Easysoft product installation found or installed unixODBC.
    The odbc.ini file is where you define your ODBC data sources. There are SYSTEM and USER DSNs. SYSTEM DSNs are stored in the file pointed to by "SYSTEM DATA SOURCES" output by odbcinst above and USER DSNs are in the file pointed to "USER DATA SOURCES". The driver manager always looks for USER DSNs before SYSTEM ones and if you want the DSN to be accessible to everyone on the machine you should make it a SYSTEM DSN.
  3. Create/check and test your DSNs with isql.
    When you install an Easysoft ODBC driver the installation will usually create a DSN in the SYSTEM odbc.ini file. Exceptions to this are if unixODBC was not installed as part of the Easysoft installation or if unixODBC was not already found on your machine.
    Check your SYSTEM odbc.ini file for the DSN to test. If your SYSTEM odbc.ini file does not contain a DSN you will need to create one - see instructions that come with the Easysoft ODBC driver you are using usually found in /usr/local/easysoft/DRIVER/docs.
    If the DSN you are using requires a username and password to login to the database you need to have these to hand.
    Run:
    UNIXODBCBIN/isql -v DSN database_username database_password
    where DSN is the name of your DSN and database_username and database_password are the login information for your database.
    This should successfully connect to your database and provide a prompt at which you can type in SQL. If it doesn't then there are a number of possibilities and you should:
    • Check you've set any necessary environment variables like ORACLE_HOME, LD_LIBRARY_PATH etc (see the manual for the Easysoft ODBC driver you are using).
    • consult the documentation that came with the ODBC driver.
    • contact Easysoft support if you have a support contract or are trialling.
    A few common problems are listed in Appendix B: Common problems accessing your DSN
  4. In order to test DBD::ODBC you need access to an ODBC DSN that points to a database in which you can create and delete tables and procedures. You should make sure you have created and tested this DSN as you will need it later.
Until this works there is no point in continuing with these instructions. DBD::ODBC is just like isql, it is another application using ODBC, so if isql does not work, DBD::ODBC won't either.

4.0 Building Perl DBI, DBD:ODBC with ODBC (not OpenVMS)

NOTE: Please check the later sections in this document for specific notes about older versions of DBD::ODBC.
NOTE: Although you can still build DBD::ODBC directly against the Easysoft ODBC-ODBC Bridge client ODBC driver, Easysoft strongly recommend you don't. Instead, select to install the unixODBC driver manager included with Easysoft ODBC driver distributions and build DBD::ODBC against that.
  1. Unpack DBI and build/test as per the instructions in the README file in the Perl DBI distribution. Install DBI.
  2. Unpack DBD-ODBC.
  3. To test DBD::ODBC you need access to an ODBC DSN that points to a database in which you can create and delete tables and procedures. See 3.0 What you need to do before attempting to use an ODBC driver in Perl.
    NOTE: Do not use the [demo] data source created by the OOB installation as this is a read-only database and the make test for DBD::ODBC needs write access.
  4. Read the README accompanying the DBD:ODBC distribution. You must define and export the following environment variables:
    DBI_DSN The dbi data source, e.g. 'dbi:ODBC:YOUR_DSN_HERE'
    DBI_USER The username to use to connect to the database
    DBI_PASS The username to use to connect to the database
    ODBCHOME The directory the unixODBC driver manager was installed in (e.g. /usr/local/easysoft/unixODBC).
    If you are using the Easysoft ODBC-ODBC Bridge you can set ODBCHOME to or the /usr/local/easysoft/oob/client and build DBD::ODBC without a driver manager and directly with the OOB client ODBC driver but Easysoft recommend you use the unixODBC driver manager. Easysoft recommend building with a driver manager as it is a more flexible configuration allowing you to use multiple ODBC drivers under Perl. Increasingly, DBD::ODBC is becoming more dependent on ODBC driver manager functionality.
    If you are not using unixODBC installed as part of an Easysoft ODBC driver distribution or you built unixODBC yourself you need to set ODBCHOME to where you installed unixODBC i.e. where --prefix was set during configure or where it was installed for you (say from an RPM). There is information in 3.0 What you need to do before attempting to use an ODBC driver in Perl which will help you locate unixODBC. Basically, DBD::ODBC takes the supplied ODBCHOME environment variable and adds /lib to it to look for the libodbc.XX shared object, and adds /include to it to find the sql*.h header files.
    NOTE: Recent versions of DBD::ODBC now try to guess what driver manager is installed and where it is, and you rarely need to set ODBCHOME now. However, if you have multiple ODBC driver managers (e.g., iODBC and unixODBC, even if they are only partly installed) DBD::ODBC will pick iODBC up before unixODBC (the reasons for this are too complicated to describe here). If you want to pick unixODBC before iODBC then add the -x switch when running the Makefile.PL.
    The DBI_DSN setting depends on the data source you have set in the odbc.ini file and tested in 3.0 What you need to do before attempting to use an ODBC driver in Perl
  5. Type perl Makefile.PL
    Ignore any warnings like "Warning: LD_LIBRARY_PATH" for now.
    NOTE: If you want to use Unicode on UNIX with DBD::ODBC you need to add the -u switch when running the Makefile.PL e.g., perl Makefile.PL -u. On Windows, DBD::ODBC currently defaults to using Unicode. For Unicode support on any platform in Perl you will need at least Perl 5.8.1. Use perl --version to see what version of Perl you have installed. For information about Unicode support in DBD::ODBC, see the DBD::ODBC documentation and changes log.
  6. Type make
  7. Make sure the database user you are using can create tables in the database as the DBD::ODBC test creates a test table.
  8. Type make test
    You may at this stage get errors like:
    install_driver(ODBC) failed: Can't load
    'blib/arch/auto/DBD/ODBC/ODBC.so
    This generally means that the ODBC driver shared object or the unixODBC driver manager shared object cannot be found by the dynamic linker. You should ensure the path to any shared objects your ODBC driver depends on and libodbc.so is on the dynamic linker search path. The method for doing this depends on the OS you are running but may mean adding a path to the LD_LIBRARY_PATH, SHLIB_PATH, LD_RUN_PATH or LIBPATH environment variables or adding the same path to /etc/ld.so.conf and running ldconfig(8) (Linux). For Easysoft ODBC drivers you will need:
    /usr/local/easysoft/lib
    /usr/local/easysoft/unixODBC/lib (or wherever you installed unixODBC)
    in the dynamic linker search path.
    Once these changes have been made rerun make test.
    If the tests still fail then you need to look at the error message. You should have used the same DSN as in 3.0 What you need to do before attempting to use an ODBC driver in Perl but if you haven't go back that section and check the DSN you are using now.
    Some Easysoft ODBC Drivers come with additional disagnostic tools like oobping which comes with the Easysoft ODBC-ODBC Bridge. If it is a connection issue consult the ODBC driver documentation at The Easysoft web site for how to diagnose.
    After connection problems are resolved any further problems should be easily identified by the ODBC error message output. However, you should be aware that the perl DBD::ODBC tests are somewhat dependent on the database and the ODBC driver you are using e.g. The Access ODBC driver does not have SQLDescribeParam.
  9. Once the tests succeed you can install Perl DBI:ODBC with "make install".

5.0 Building Perl DBI and DBD::ODBC with OOB (OpenVMS)

5.1 On OpenVMS/Alpha

These instructions are specific to using the Easysoft ODBC-ODBC Bridge with Perl on OpenVMS/Alpha.
Easysoft has built and tested Perl 5.8.1 with DBI-1.35 and DBD::ODBC 1.05. We have also built and tested Perl 5.6.0 with DBI-1.13 and DBD::ODBC 0.28 (please see separate instructions later in this document if you need to use versions of DBD::ODBC before 1.00).
The build for Perl 5.8.1 we tested was the snapshot at http://www.iki.fi/jhi/perl@18983.tgz.
We used MMS 3.2-01 throughout as our copy of MMK appeared to give errors like:
%MMK-F-SDCMIX, single/double-colon dependency mix found for target
RE_EXEC.OBJ
%MMK-F-ERRUPD, error status %x1c148064
We also used DECC V6.0-001 on OpenVMS V7.2.
All the tools you need to uncompress and unpack Perl and the DBI/DBD modules may be found off the VMS Perl site (see Useful links).
  1. If you have not yet installed Perl, get Perl 5.8.1 (or newer), unpack it and run the configure.com. Answer all the questions, run mms, mms test and if OK, mms install. You will find instructions at http://www.sidhe.org/vmsperl/readme.vms.html.
    When we did this we got one failure:
    lib/vmsish...........................FAILED at test 22
    This was a problem for people with positive offset from GMT and a patch was posted on the vmsperl mailing list. It does not however cause a problem.
  2. Get the latest Perl DBI module, uncompress and unpack. Read the README. The sequence you need is described below but please make sure you read all this section first as you will need to edit the Makefile.PL and DBD.PM files.
    perl Makefile.PL
    mms
    mms test
    mms install
    With DBI-1.35 and this Perl snapshot we had two problems with the descrip.mms generated from the Makefile.PL by MakeMaker:
    • "%MMS-F-GWKNOACTS, Actions to update CONFIG
      are unknown."
      This seems to be caused by a rule with no action. If you search Makefile.PL for the line:
      config :: $(changes_pm)
      
      add on the next line:
      $(NOECHO) $(NOOP)
      
      Make sure you put a tab before "$(NOECHO)".
    • "%MMS-F-GWKNOACTS, Actions to update
      [.BLIB.ARCH.AUTO.DBI]DRIVER.XST are unknown."
      This seems to be caused by the lines generated by MakeMaker commented as "these two keep make -j4 working". In [.lib.DBI]DBD.pm search for:
      # these two keep make -j4 working
              $(DBI_DRIVER_XST) :: pm_to_blib
              '.$xstf_h.' :: pm_to_blib
      
      and add to each rule:
      $(NOECHO) $(NOOP)
      
      so you have:
      # these two keep make -j4 working
              $(DBI_DRIVER_XST) :: pm_to_blib
                      $(NOECHO) $(NOOP)
              '.$xstf_h.' :: pm_to_blib
                      $(NOECHO) $(NOOP)
      
      Make sure you put a tab before "$(NOECHO)".
    If you need to make these changes you need to rerun perl Makefile.PL.
    You might have to specify the target as "all" as mms picks the first target in the descrip.mms file and you might get an error because some of the [.blib] directory structure was not created.
    When building DBI, you will probably see a few warnings about symbols being trimmed as they are very long - don't worry about this.
    You may also see %SYSTEM-W-BADFILEVER errors for dbiprof.pl.rno, dbiproxy.pl.rno and possibly dbish.pl.rno (pre 1.35). This problem is due to the double file extension which is invalid in OpenVMS but we currently do not know the solution (you can ignore it).
    When testing DBI, we got no errors. Some tests for iThreads, PurePerl (Kids, profiling, preparse) were skipped.
  3. Get the latest DBD::ODBC, uncompress and unpack. OOB was verified with DBD::ODBC 1.05 but it needs a patch to work properly on OpenVMS with OOB. Versions after DBD::ODBC 1.05 may include the required patch.
    You can get GNU patch for OpenVMS from Useful Links at the bottom of this document, apply the patch by hand (not difficult but possibly error prone) or apply the patches on a machine where you already have GNU patch. The patch is included in the extras sub directory of the OOB distribution and is called [.DBD_ODBC_1_05]DBD-ODBC-1_05_VMS.PATCH.
    If you are applying the patch by hand with reference to the patch file you need to remove all lines starting with '-' and add all lines starting with '+'. Otherwise unpack DBD::ODBC, change into the created directory and run:
        patch --verbose --backup --input=DBD-ODBC-1_05_VMS.PATCH -p0
    If you can't get GNU patch or don't understand enough about patch files to make the changes necessary you can try editing Makefile.PL and making the following changes:
    Change
    $myodbc = 'esodbc'
            if !$myodbc && <$odbchome/*esoobclient*>;
    
    to
    $myodbc = 'esodbc'
            if !$myodbc && <$odbchome/lib/*esoobclient*>;
    
    and search for the section starting:
    elsif ($myodbc eq 'esodbc')
    
    In this block look for occurances of "$odbchome" used without a following '/' and add "/lib" so "$odbchome" becomes "$odbchome/lib". You also need to locate the "-leasyrpc" and add "-lextras". You should end up with something like this (comments have been omitted and changed lines are marked with ->):
    The reason for this change is that the OOB distribution has changed to put the libraries in [.odbchome.lib] whereas they were in [.odbchome] before and additional functions are in libextras.olb.
    You now need to define where you installed OOB. You do this by defining the ODBCHOME logical as the directory where the OOB client was installed. e.g. suppose you installed OOB in DKA200:[MARTIN.OOB] you need to:
    define/log ODBCHOME DKA200:[MARTIN.OOB]
    
    You also need to define a logical called DBI_DSN which specifies the DBD ODBC driver and the data source name. Create a local OOB client data source called test in the file []odbc.ini. which points to a remote data source e.g.
        [test]
        serverport = ntserver:8888
        targetdsn = ntsystemdsn
        logonuser = nt_username
        logonauth = nt_password
    Then define DBI_DSN as:
    define/log DBI_DSN "dbi:ODBC:test"
    
    then define DBI_USER as:
    define/log DBI_USER "database_username"
    
    then define DBI_PASS as:
    define/log DBI_PASS "database_password"
    
    You can now run:
        perl Makefile.PL
    to generate the mms description file.
    Before continuing the build we should mention a few problems we came across that need minor alterations to the Makefile.PL file.
    With DBD-ODBC 1.05 and this Perl snapshot we had a similar problem as with DBI (above) except the MMS-F-GWKNOACTS for DRIVER.XST goes away if DBI is installed first. The descrip.mms generated from the Makefile.PL by MakeMaker produces these errors:
    • "%MMS-F-GWKNOACTS, Actions to update CONFIG
      are unknown."
      This seems to be caused by a rule with no action. If you search the Makefile.PL for the line:
      config :: $(changes_pm)
      
      add to the next line:
      $(NOECHO) $(NOOP)
      
      Make sure you put a tab before "$(NOECHO)".
    • "%MMS-F-GWKNOACTS, Actions to update
      [.BLIB.ARCH.AUTO.DBI]DRIVER.XST are unknown."
      This seems to be caused by the lines generated by MakeMaker commented as "these two keep make -j4 working". In Makefile.PL search for:
      # these two keep make -j4 working
              $(DBI_DRIVER_XST) :: pm_to_blib
              $(DBI_INSTARCH_DIR)Driver_xst.h :: pm_to_blib
      
      and add to each rule:
      $(NOECHO) $(NOOP)
      
      so you have:
      # these two keep make -j4 working
              $(DBI_DRIVER_XST) :: pm_to_blib
                  $(NOECHO) $(NOOP)
              $(DBI_INSTARCH_DIR)Driver_xst.h :: pm_to_blib
                  $(NOECHO) $(NOOP)
      
      Make sure you put a tab before "$(NOECHO)".
    If you need to make these changes you need to rerun perl Makefile.PL.
        mms
    Do not be surprised if the build shows some IMPFUNC, PTRMISMATCH, PROMOTMATCHW or OUTTYPELEN informational messages - these are normal.
    You can now test DBD::ODBC using the OOB ODBC driver:
        mms test
    and finally install DBD::ODBC using:
        mms install

5.2 On OpenVMS/Itanium

These instructions are specific to using the Easysoft ODBC-ODBC Bridge with Perl on OpenVMS/Itanium.
Easysoft has built and tested Perl 5.8.8 with DBI-1.51 and DBD::ODBC 1.13.
We used the following versions:
  • OpenVMS 8.2-1
  • HP C V7.1-011 on OpenVMS IA64 V8.2-1
  • Installed VMS821I-PCSI-V0100 upgrade
  • vmstar (built from sources found in sys$common:[GNV.src.GNV.VMSTAR]
and our machine was running ODS5.
We first tried installing a Perl 5.8.6 binary from HP’s site but we had a few problems with it like mms clean failing with an access violation. If you’ve got the same problem:
perl "-MExtUtils::Command" -e "rm_f" foo.[0-9][0-9]
dies with an access violation.
After HP’s binary failed we downloaded the 5.8.8 source release of perl and used that.

5.2.1 Prerequisites

Install a binary of vmstar or build it yourself. After the installation of VMS 8.2-1 we found the vmstar source files in sys$common:[GNV.src.GNV.VMSTAR].
  set def sys$common:[GNV.src.GNV.VMSTAR]
  mms clean
  mms
  copy VMSTAR.ALPHA_EXE VMSTAR.EXE
  vmstar :== $sys$common:[GNV.src.GNV.VMSTAR]vmstar.exe
Now vmstar is a symbol pointing to the vmstar executable.

5.2.2 Building/Installing Perl 5.8.8

Download the source for Perl 5.8.8.
Use vmstar to untar it.
  vmstar xovf stable.tar
will create the sub directory perl-5_8_8.
Read the README.vms, then read it again.
Configure perl (see the README.vms file). We used:
  @ Configure "-d" "-Dprefix=dka0:[perl]"
because we wanted to take all the defaults except we wanted Perl installed in dka0:[perl].
Then type the command that Configure tells you to enter to build Perl - usually "mms".
If the build fails scroll back through the build process and look for warnings like:
%MMS-W-GMFUTURE, Time for [-.BLIB.MAN3].EXISTS is in the future:
6-AUG-2006 12:29:13.00
If you find these warnings you have probably got the same time issue we had originally which we have only found one solution to. If you can provide a better solution than we describe here please let us know. For your information, when hit this problem:
  @SYS$MANAGER:UTC$TIME_SETUP SHOW
produced:
  AUTO_DLIGHT_SAV is set to "0" and DTSS is not in use.
  You will have to manually change to/from Daylight Saving Time.
  
  You can do this by executing SYS$MANAGER:UTC$TIME_SETUP.COM,
  or you can use SYS$EXAMPLES:DAYLIGHT_SAVING.COM.
  
  
      LOCAL TIME ZONE          = GB -- DAYLIGHT TIME
      LOCAL SYSTEM TIME        =  6-AUG-2006 11:20:11.58 (BST)
      TIME DIFFERENTIAL FACTOR = 1:00
      TIME ZONE RULE           = GMT0BST-1,M3.4.0/01,M10.5.0/02
      Change GMT to BST on the Fourth Sunday of March (26-Mar-2006) at
  01:00
      Change BST to GMT on the Last Sunday of October (29-Oct-2006) at
  02:00
The only thing that worked for use was the following change:
  --- lib/ExtUtils/Command.pm;-0  Fri Oct 21 03:55:12 2005
  +++ lib/ExtUtils/Command.pm     Sun Aug  6 13:30:45 2006
  @@ -149,12 +149,11 @@ Makes files exist, with current timestam
   =cut
  
   sub touch {
  -    my $t    = time;
       expand_wildcards();
       foreach my $file (@ARGV) {
           open(FILE,">>$file") || die "Cannot write $file:$!";
           close(FILE);
  -        utime($t,$t,$file);
  +        utime(undef,undef,$file);
       }
   }
Edit the file [.lib.ExtUtils]Command.pm, delete the lines starting in a '-' and add the lines starting in a '+'.
Rerun mms.
Run:
  mms test
We got the following errors:
  t/io/fs...................................FAILED at test 5
  t/op/stat.................................FAILED at test 33
  ext/Devel/PPPort/t/ppphtest...............FAILED--unexpected output at test 0
  ext/List/Util/t/p_tainted.................FAILED--no leader found
  ext/List/Util/t/weak......................FAILED--unexpected output at test 7
  lib/ExtUtils/t/basic......................FAILED at test 67
  lib/ExtUtils/t/Command....................FAILED at test 8
  lib/ExtUtils/t/Constant...................FAILED at test 23
  lib/ExtUtils/t/FIRST_MAKEFILE.............FAILED at test 4
  lib/ExtUtils/t/PL_FILES...................FAILED at test 3
  lib/vmsish................................FAILED at test 22
  
  Failed 13 test scripts out of 892, 98.54% okay.
  ### Since not all tests were successful, you may want to run some of
  ### them individually and examine any diagnostic messages they produce.
  ### See the INSTALL document’s section on "make test".
  ### You have a good chance to get more information by running
  ###   ./perl harness
  ### in the 't' directory since most (>=80%) of the tests succeeded.
  u=40.80  s=0.00  cu=0.00  cs=0.00  scripts=892  tests=114061
We don’t know as yet whether these are test bugs or geniune errors but they don’t appear to affect using Perl DBI or DBD::ODBC although they may affect other operations in Perl.
Run
  mms install
to install Perl in your chosen path.
if it hangs with:
  $ mms install
  
  %DCL-I-SUPERSEDE, previous value of PERL_ROOT has been superseded
  %DCL-I-SUPERSEDE, previous value of PERLSHR has been superseded
  If F$TrnLnm("Sys") .nes. "" Then Deass SYS
  MCR Sys$Disk:[]miniperl.exe "-I[.lib]" installperl
  Deep recursion on subroutine "File::Path::mkpath" at lib/File/Path.pm line 162.
you may want to consult the following references:
What we did to get around this problem was to create the directory where Perl is going to be installed before running mms install and this appears to work around this issue.
Running h2ph to generate the Perl copies of your header files produced:
  Cannot open perl_root:[lib.site_perl.VMS_IA64]/_h2ph_pre.ph: file
   specification syntax error at perl_root:[utils]h2ph.com line 741.
   %RMS-F-SYN, file specification syntax error
but you can ignore this as it does not affect the installation of DBI or DBD::ODBC.
Now you have Perl installed run the perl_setup.com which is placed in the directory where you installed Perl.

5.2.3 Building/Installing Perl DBI

Download DBI-1.51 and unpack it with vmstar as above.
Use the normal sequence of:
  perl Makefile.pl
  mms
  mms test
  mms install
We got the warnings like the one which follows which we believe you can safely ignore:
  Warning: long symbol DBD__Perl__db_selectall_arrayref
          trimmed to DBD_Perl_db_selectal_arayref

5.2.4 Building/Installing Perl DBD::ODBC

Download the OOB Client, unzip it wherever you want it and make a note of the directory you installed it in. In this example we assume you installed it in dka0:[oob].
Set up the following logicals:
  define/log ODBCHOME DKA0:[OOB]
  define/log DBI_DSN "dbi:ODBC:test"
  define/log DBI_USER "database_username"
  define/log DBI_PASS "database_password"
You will need to change ODBCHOME to wherever you installed OOB. DBI_DSN defines the DBD driver to use and the data source to use (we’ve used a data source called "test" here). DBI_USER and DBI_PASS are the database username and password required to login to your data source (amend as appropriate).
Create an odbc.ini file in the current working directory ([]) which contains:
    [test]
    serverport = ntserver:8888
    targetdsn = ntsystemdsn
    logonuser = nt_username
    logonauth = nt_password
where:
  • serverport is the name of the machine where you installed the OOB Server and the port it is listening on (usually 8888).
  • targetdsn is the name of a SYSTEM DSN you have created on ntserver which is a working DSN using the remote ODBC driver you want to access.
  • logonuser and logonauth are a valid username and password to login to ntserver i.e. the username and password you would use to login to that machine at its console.
Edit the Makefile.PL and replace occurrances of ptrmismatch with ptrmismatch1. this is because decc has changed the warning from ptrmismatch to ptrmismatch1.
Create a file in [] called continue.com containing one empty DCL line e.g.
  $
We think this is a bug in ExtUtils::MakeMaker but it defined a NOOP command in the mms descrip.mms file as continue.com and if you attempt to run mms without it you will get an error like this:
  MCR dka0:[perl]perl.exe "-MExtUtils::Command" -e cp Changes
  [.blib.lib.DBD.ODBC]Changes.pm
  @Continue
  %DCL-E-OPENIN, error opening DKA0:[NICK.MARTIN.DBD-ODBC-1_13]Continue.COM; as
  input
  -RMS-E-FNF, file not found
  %MMS-F-ABORT, For target CONFIG, CLI returned abort status: %X10018292.
We used MMS 3.2-01 throughout as our copy of MMK appeared to give errors like:
%MMK-F-SDCMIX, single/double-colon dependency mix found for target
RE_EXEC.OBJ
%MMK-F-ERRUPD, error status %x1c148064
We also used DECC V6.0-001 on OpenVMS V7.2.
Type
  mms
As with DBI, you can safely ignore the warnings like:
Warning: long symbol DBD__ODBC__db_selectall_arrayref
        trimmed to DBD_ODBC_db_selectal_arayref
All the tools you need to uncompress and unpack Perl and the DBI/DBD modules may be found off the VMS Perl site (see links below).
Now, if you OOB Server is up and running, you;ve set up the odbc.ini file in the current working directory correctly and created a working SYSTEM DSN on the OOB Server machine that works you can run:
  mms test
We got failures in 02simple.t for the data sources test because we are not using an ODBC driver manager (safe to ignore) and errors in 20SqlServer.t test 5 which look like:
  1..37
  ok 1 - use ODBCTEST;
  ok 2 - use Data::Dumper;
  ok 3 - errors on data comparison
  ok 4 - temporary table handling
  Can't change param 1 maxlen (51->50) after first bind at t/20sqlserver.t line
  180.
  # Looks like you planned 37 tests but only ran 4.
  # Looks like your test died just after 4.
You can fix this problem by editing the dbdimp.c module. Look for the line:
else if (maxlen && maxlen != phs->maxlen) {
at around line 2931 and change it to:
else if (maxlen && maxlen > phs->maxlen) {
You can now run:
  mms install
to install DBD::ODBC.

6.0 Notes about old versions of DBI and DBD::ODBC

6.1 A note about DBD::ODBC up to 0.45 and SQL_WLONGVARCHAR

Versions of DBD::ODBC from 0.25 conditionally build with support for SQL_WLONGVARCHAR. A problem can arise in OOB when DBD::ODBC is built directly with OOB or unixODBC which manifests itself as the error:
[unixODBC][Easysoft ODBC (Server)]Memory allocation error
(SQL-S1001)(DBD: describe/SQLBindCol err=-1)
This occurs when you issue a query returning a SQL_WLONGVARCHAR (ntext in MS SQL Server) column. DBD::ODBC only builds support for SQL_WLONGVARCHAR if SQL_WLONGVARCHAR is defined in the ODBC headers it is built with. When built without support for SQL_WLONGVARCHAR if a SQL_WLONGVARCHAR column is encountered it is bound with the column size returned by SQLDescribeCol instead of LongReadLen. The Makefile.PL that comes with DBD::ODBC does not ensure sqlucode.h is written to dbdodbc.h when building with OOB and unixODBC. You can correct this by adding a "#include <sqlucode.h>" to dbdodbc.h after running perl Makefile.PL or by editing the "esodbc" or "unixodbc" sections of Makefile.PL and adding "print SQLH qq{#include <sqlucode.h>\n};" to the end.
Please also read the notes for 0.24 and 0.25 for further information.

6.2 A note about DBD::ODBC 0.28

If you are building DBD::ODBC with the unixODBC driver manager then you should note there was a change in unixODBC which requires a small modification to DBD::ODBC's Makefile.PL prior to building DBD::ODBC. The following entry from the OOB FAQ describes the problem:
4.42 Why do I get "undefined symbol: SQLParamData" when testing DBD::ODBC?
When building DBD::ODBC with unixODBC and running the make test you see something like this:
PERL_DL_NONLAZY=1 /usr/bin/perl -Iblib/arch -Iblib/lib
-I/usr/lib/perl5/5.00503/i386-linux -I/usr/lib/perl5/5.00503 -e 'use
Test::Harness qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
t/01base............install_driver(ODBC) failed: Can't load
'blib/arch/auto/DBD/ODBC/ODBC.so' for module DBD::ODBC:
blib/arch/auto/DBD/ODBC/ODBC.so: undefined symbol: SQLParamData at
/usr/lib/perl5/5.00503/i386-linux/DynaLoader.pm line 169.
The undefined symbol SQLParamData is reported by the dynamic linker as the first symbol it looked for but could not find.
This happens when building DBD::ODBC with unixODBC because the Makefile.PL is now incompatible with newer unixODBC releases. The Makefile.PL searches ODBCHOME/lib for *odbc*.* and finds libodbc.so AND libodbcinst.so. It then goes on to choose libodbcinst.so which is the incorrect shared object. You can check this by running ldd on blib/arch/auto/DBD/ODBC/ODBC.so where you will probably see something like:
libodbcinst.so1 (libc6) => /usr/local/easysoft/unixODBC/lib/libodbcinst.so1
To fix this edit the Makefile.PL and delete the second '*' in the line:
elsif ($myodbc eq 'unixodbc') {
        my @ilibs = <$odbchome/lib/*odbc*.*>;
so it becomes:
elsif ($myodbc eq 'unixodbc') {
        my @ilibs = <$odbchome/lib/libodbc.*>;
Now rerun perl Makefile.PL and it should pick up the correct libodbc shared object.

6.3 A note about DBD::ODBC 0.27

See 0.25 and 0.24.

6.4 A note about DBD::ODBC 0.25

0.25 is like 0.24 except the SQL_Wxyz wide character support is conditionally compiled in if your ODBC driver defines wide characters. If you want wide character support please follow the instructions below for 0.24.

6.5 A note about DBD::ODBC 0.24

A change was made to DBD::ODBC 0.24 which sometimes prevents it building with OOB (and a number of other ODBC drivers and driver managers) out of the box. From DBD::ODBC 0.24, the driver appears to be required to define SQL_Wxyz data types. The header files that come with OOB do define the SQL_Wxyz data types but only if the WIN32, __unix__ or __vms__ macros are defined. If your compiler does not define any of these (you will get undefined references to SQL_WVARCHAR etc) you will need to modify the generated Makefile (see below) to add a -D__unix__ to the definition of CCFLAGS. Whether your compiler defines __unix__ or not you should add -DSQL_NOUNICODEMAP to CCFLAGS too.
We hope this situation will be rectified in a future release of DBD::ODBC.

6.6 A note about versions of DBD::ODBC before 0.21

Prior to DBD::ODBC 0.21, DBD::ODBC did not require a driver manager. This changed in DBD::ODBC 0.21 and it is assumed versions thereafter. The Easysoft ODBC-ODBC Bridge does not require a driver manager on non-Windows platforms to work as it was written before ODBC 3.0 driver managers were available for UNIX and it contains all the necessary driver manager functionality. However, from DBD::ODBC 0.21, DBD::ODBC requires the ODBC driver manager APIs SQLDrivers and SQLDataSources. These functions were not available in versions of OOB prior to the 0.4.0.0 beta but are included from 0.4.0.0 onwards.
If you are building DBD::ODBC 0.20 then you must apply the patch supplied with OOB in the extras/DBD_ODBC_0.20 subdirectory off the OOB installation path. If you have not got patch the changes are minimal and can easily be hand edited by inserting the lines starting with a "+" in the patch file.
e.g.
patch < Makefile.PL.patch
Do not attempt to apply this patch to DBD::ODBC 0.21 as Jeff Urlwin has already applied it and the Makefile.PL that comes with 0.21 is fine.
DBD::ODBC 0.21 contains the iODBC driver manager distribution and OOB will work with this driver manager. However, if you want/need to use a driver manager then Easysoft recommend the unixODBC driver manager available from unixodbc.org. There are a number of reasons for this:
  1. The unixODBC project started by Peter Harvey is now maintained by Nick Gorham who is an Easysoft developer. This means there is much greater experience with unixODBC within Easysoft and we will be able to provide better support for OOB running under unixODBC. It also means that if you find a problem in unixODBC it is much easier for us to facilitate a fix.
  2. At this time unixODBC supports ODBC 3.5 and is thread-safe whilst this is not true for iODBC.
  3. The unixODBC package contains much more than a driver manager. The aim of the unixODBC project is to provide all the ODBC functionality available on Windows for UNIX operating systems. The unixODBC package may be built with the QT libraries to allow GUI configuration of DSNs and drivers. It also contains the GUI DataManager program which may be used to explore your ODBC data.
  4. From OOB 0.4.0.0, the OOB installation for UNIX can automatically install itself using the unixODBC installer program to run under unixODBC.
To summarise the situation:
  1. If you have DBD::ODBC 0.20 then you can directly build DBD with any version of OOB and you do not need to use a driver manager unless you want to support multiple ODBC drivers through Perl.
  2. If you have DBD::ODBC 0.21+, then you can do as in [1] but you will require OOB 0.4.0.0 (or above).
  3. If you want to use a driver manager or need to because you have multiple ODBC drivers then Easysoft recommend the unixODBC manager. OOB will however work with the iODBC driver manager.

6.7 Building Perl 5.6.0, DBI 1.13 and DBD:ODBC 0.28 with OOB (OpenVMS)

These instructions are specific to using the Easysoft ODBC-ODBC Bridge with Perl on OpenVMS.
Easysoft has built and tested Perl 5.6.0, DBI-1.13 and DBD::ODBC 0.28, although a patch to DBD::ODBC is required to build with OOB (see later).
We used MMS 3.2-01 throughout as our copy of MMK appeared to give errors like:
%MMK-F-SDCMIX, single/double-colon dependency mix found for target
RE_EXEC.OBJ
%MMK-F-ERRUPD, error status %x1c148064
We also used DECC V6.0-001 on OpenVMS V7.2.
All the tools you need to uncompress and unpack Perl and the DBI/DBD::ODBC modules may be found off the VMS Perl site (seeUseful Links below).
  1. If you have not yet installed Perl, get Perl 5.6.0 (or newer), unpack it and run the configure.com. Answer all the questions, run mms, mms test and if OK, mms install.
    When we did this we got three failures:
        glob-basic - failed on test 3
        vmsish - failed on test 7
        warnings - failed on test 216
    It is our understanding that the glob failure is due to the fact that the test does not take into account that glob() works differently on OpenVMS. There are patches for vmsish on the vmsperl mailing list.
  2. Get the latest Perl DBI module, uncompress and unpack. Read the README. You should be able to simply do:
        perl Makefile.PL
        mms all
        mms test
        mms install
    Make sure you specify the target as "all" or mms picks the first target in the descrip.mms file and you will probably get an error because the [.blib] directory structure was not created e.g.
        %MMS-F-GWKNOPRN, There are no known sources for the current target
        [.BLIB.ARCH.AUTO.DBI]DRIVER.XST
    When building DBI, you will probably see a few warnings about symbols being trimmed as they are very long - don't worry about this.
    You may also see %SYSTEM-W-BADFILEVER errors for dbiproxy.pl.rno and dbish.pl.rno. This problem is due to the double file extension which is invalid in VMS but we currently do not know the solution.
    When testing DBI, we got errors from examp.t:
        t/examp
        can't run t/examp.t. invalid argument
        FAILED before any test output arrived
    Usually when this happens the best thing to do is rerun the tests with TEST_VERBOSE=1 set e.g. mms/macro=TEST_VERBOSE=1 test however, as the test did not run this does not help. However, if you change into the t subdirectory and run the examp test individually the test succeeds. e.g.
        set def [.t]
        perl -"T" examp
    We have found a reference in the vmsperl mailing list to this which suggests the test calls Perl with a command line that is much too long while passing a library list explicitly
  3. Get the latest DBD::ODBC, uncompress and unpack. OOB was verified with DBD::ODBC 0.28 but the Makefile.PL needs a patch to work properly on VMS. Versions after DBD::ODBC 0.28 may include the required patch (you can check by searching for the string VMS in the DBD::ODBC Makefile.PL file).
    You can get GNU patch for VMS from Useful Links, apply the patch by hand (not difficult but possibly error prone) or apply the patches on a machine where you already have patch. The patch is included in the extras subdirectory of the OOB distribution and is called [.DBD_ODBC_0_28.DBD-ODBC-0_28_VMS.PATCH].
    If you are applying the patch by hand you need to remove all lines starting with - and add all lines starting with +. Otherwise unpack DBD::ODBC, change into the created directory and run:
        patch --verbose --backup --input=DBD-ODBC-0_28_VMS.PATCH -p0
    You now need to define where you installed OOB. You do this by defining the ODBCHOME logical as the directory where the OOB client was installed. e.g. suppose you installed OOB in DKA200:[MARTIN.OOB] you need to:
    define/log ODBCHOME DKA200:[MARTIN.OOB]
    
    You also need to define a logical called DBI_DSN which specifies the DBD ODBC driver and the data source name. Create a local OOB client data source called test in the file []odbc.ini. which points to a remote data source e.g.
        [test]
        serverport = ntserver:8888
        targetdsn = ntsystemdsn
        logonuser = nt_username
        logonauth = nt_password
        targetuser = db_username
        targetauth = db_password
    Then define DBI_DSN as:
    define/log DBI_DSN "dbi:ODBC:test"
    
    You can now run:
        perl Makefile.PL
        mms all
        mms test
        mms install

7.0 Examples

Some Easysoft ODBC drivers contain Perl examples in the examples subdirectory of the driver.
There are some test programs in addition to those mentioned above in the Perl DBD:ODBC distribution in the mytest subdirectory of DBD-ODBC (listtabs.pl and testfunc.pl). Unfortunately, listtabs.pl seems to be a little out of date in respect of Perl DBI as it expects a statement handle from the tables method and expects to find a fetchrow method.

8.0 Issues

8.1 Bound Parameters and MS Access

Perl DBD:ODBC may sometimes use bound parameters but this requires support for SQLDescribeParam. The MS Access ODBC driver does not currently support SQLDescribeParam and so bound parameters must be avoided when using Perl->MS Access or Perl->OOB->MS Access.

8.2 Memory Leak Bug

On March 30th 2001 Tim Bunce (author of DBI) reported the following bug to perl5-porters:
----- Forwarded message from Tim Bunce <Tim.Bunce@ig.co.uk> -----
Date: Fri, 30 Mar 2001 15:38:27 +0100
From: Tim Bunce <Tim.Bunce@ig.co.uk>
To: Perl 5 porters <perl5-porters@perl.org>
Cc: Tim Bunce <timbo@ig.co.uk>
Subject: Memory leak localizing a tied variable

The script appended below demonstrates a memory leak when doing a
local() on a tied variable.

I found this because someone reported that local($dbh->{RaiseError})=1
(and similar) leaked memory and thought it maybe a DBI bug.
The script demonstrates that it's not.

Perl 5.005 and 5.006 leak but 5.004 doesn't. I've not got a 5.7.0
handy. I'd be grateful if someone could test it on the current bleadperl.

Thanks.

Tim.
#!/usr/local/bin/perl -w

print "localizing tied variable leak test for perl $]...\n";
# 5.006   does leak
# 5.00503 does leak
# 5.00404 doesn't leak

use strict;
use Tie::Hash;
tie my %tie_hash => 'Tie::StdHash';

my $count = 0;
my $ps = (-d '/proc') ? "ps -lp " : "ps -l";

mem_test() while 1;

sub mem_test {
    system("echo $count; $ps$$") if (($count++ % 1000) == 0);
    local($tie_hash{Foo}) = 1;
}
----- End forwarded message -----

Conmecting perl on unix or linux

Connecting Perl on UNIX or Linux to Microsoft SQL Server - Perl DBI/DBD::ODBC Tutorial Part 3

This tutorial shows you how to access MS SQL Server databases from Perl on UNIX and Linux.

Connect Perl to SQL Server 2000, SQL Server 2005, SQL Server 2008, SQL Server 2012, SQL Server 2014 and SQL Server Express

When developing this tutorial, we accessed SQL Server 2000–2014 and Express databases from Perl on UNIX and Linux.

Perl and Linux

To access SQL Server from Perl on Linux, we used Easysoft ODBC drivers with Perl DBI and DBD::ODBC on Debian GNU/Linux, RedHat and Ubuntu (Edgy Eft, Feisty Fawn, Gutsy Gibbon and Hardy Heron). Easysoft ODBC drivers should work with any recent 32-bit or 64-bit Linux distribution—CentOS, Fedora, Kubuntu, Mandrake/Mandriva, OpenSUSE/SUSE, RedHat Enterprise Linux (RHEL), Slackware and so on.
Access MS SQL Server 7.0, 2000, 2005, 2008, 2012, 2014 and Express from Perl on UNIX and Linux.

Pre-requisites

The pre-requisite software for this tutorial is:
  1. Perl We used Perl 5.8, but you only need the minimum version required by the DBI and DBD::ODBC modules, which is currently 5.6. Use perl --version to see what version of Perl you have installed.
  2. DBI module We used DBI 1.45 and DBI 1.607, but the samples in this tutorial should work with anything after 1.40. To see if you have a recent enough version of DBI installed, run:
      perl -e 'use DBI 1.40;'
    If you get an error like "DBI version 1.40 required--this is only version 1.30 at -e line 1.", you need to upgrade DBI.
    If you get an error saying "DBI cannot be found in @INC", you have probably not got DBI installed.
    Go to CPAN to get an up to date version of the DBI module.
  3. DBD::ODBC We used DBD::ODBC 1.11 and DBD::ODBC 1.17. You can use similar methods to the ones shown above to check whether DBD::ODBC is installed and to see what version you have.
    To check that you have the DBD::ODBC module installed:
      perl -e 'use DBD::ODBC;'
    If you have not got DBD::ODBC installed, see Enabling ODBC support in Perl with Perl DBI and DBD::ODBC for installation instructions.
    To show the DBD::ODBC version:
      perl -MDBD::ODBC -e 'print $DBD::ODBC::VERSION;'
    To show all drivers DBI knows about and their versions:
      perl -MDBI -e 'DBI->installed_versions;'
  4. SQL Server ODBC driver We used our UNIX/Linux ODBC driver for SQL Server 7.0, 2000, 2005, 2008 and Express to connect Perl to a remote SQL Server database:
    1. Download the SQL Server ODBC driver for your Perl client platform. (Registration required.) If the SQL Server ODBC driver is not currently available for your platform, check the list of ODBC-ODBC Bridge Client platforms. The ODBC-ODBC Bridge is an alternative SQL Server solution from Easysoft.
    2. Install and license the SQL Server ODBC driver on the machine where Perl is installed. See which environment variables you need to set (LD_LIBRARY_PATH, LIBPATH, LD_RUN_PATH, SHLIB_PATH depending on the driver, platform and linker).
    3. Create an ODBC data source in /etc/odbc.ini that connects to the SQL Server database you want to access from Perl. For example, this SQL Server ODBC data source connects to a SQL Server Express instance that serves the Northwind database:
      [MSSQL-Perl]
      Driver                  = Easysoft ODBC-SQL Server
      Server                  = my_machine\SQLEXPRESS
      User                    = my_domain\my_user
      Password                = my_password
      # If the database you want to connect to is the default
      # for the SQL Server login, omit this attribute
      Database                = Northwind
    4. Use isql to test the new data source. For example:
      cd /usr/local/easysoft/unixODBC/bin
      ./isql -v MSSQL-Perl
      At the prompt, type "help" to display a list of tables. To exit, press return in an empty prompt line.

Assumptions

  1. Previous tutorials in this series This tutorial assumes you have read or understand all the concepts covered in the previous tutorials DBD::ODBC Tutorial Part 1 - Drivers, Data Sources and Connection and DBD::ODBC Tutorial Part 2 - Introduction to retrieving data from your database.
  2. Operating system This tutorial was designed on UNIX and Linux, and we have assumed you are using UNIX or Linux too. However, all the Perl examples should work equally well on Windows so long as minor alterations for the command line are made.
  3. ODBC driver manager We have assumed that you are using the unixODBC driver manager. All discussion in this document relating to the location and definition of ODBC data sources is for unixODBC.

Accessing Microsoft SQL Server from Perl on UNIX or Linux

Testing Your Data Source

The following script selects and fetches some test data. Use it to check that you can successfully access your data source from a Perl script. Remember to replace the data source name and database username and password placeholders with appropriate values for your database.
#!/usr/bin/perl -w
use strict;

use DBI;

# Replace datasource_name with the name of your data source.
# Replace database_username and database_password
# with the SQL Server database username and password.
my $data_source = q/dbi:ODBC:datasource_name/;
my $user = q/database_username/;
my $password = q/database_password/;

# Connect to the data source and get a handle for that connection.
my $dbh = DBI->connect($data_source, $user, $password)
    or die "Can't connect to $data_source: $DBI::errstr";

# This query generates a result set with one record in it.
my $sql = "SELECT 1 AS test_col";

# Prepare the statement.
my $sth = $dbh->prepare($sql)
    or die "Can't prepare statement: $DBI::errstr";

# Execute the statement.
$sth->execute();

# Print the column name.
print "$sth->{NAME}->[0]\n";

# Fetch and display the result set value.
while ( my @row = $sth->fetchrow_array ) {
   print "@row\n";
}

# Disconnect the database from the database handle.
$dbh->disconnect;

Where to Go Now

After you have tested your data source you are ready to start fetching and manipulating the data in your database from Perl. We suggest you take a look at DBD::ODBC Tutorial Part 2 - Introduction to retrieving data from your database or the excellent book "Programming the Perl DBI", which you can find at http://dbi.perl.org.
The rest of this tutorial concerns itself with MS SQL Server specific issues and common questions from people accessing MS SQL Server from Perl.

Calling Procedures

The following section shows you how to create and call SQL Server procedures that accept input and return output.
To use the sample scripts in this section you need a SQL Server database in which you can create and delete tables and procedures. The data source that you specify in the scripts needs to connect to this database.

Input Parameters

Input parameters are used to supply values to a procedure. For example, a procedure that executes a SELECT statement might use an input parameter to supply a value in a WHERE clause. You provide input parameter values when the procedure is called.
The following example script shows how to create a procedure that accepts one input parameter. The procedure adds 1 to the input parameter value and returns the new value. The script calls the procedure and displays the return value.
#!/usr/bin/perl -w
use strict;

use DBI;

# Replace datasource_name with the name of your data source.
# Replace database_username and database_password
# with the SQL Server database username and password.
my $data_source = q/dbi:ODBC:datasource_name/;
my $user = q/database_username/;
my $password = q/database_password/;
my $dbh = DBI->connect($data_source, $user, $password)
    or die "Can't connect to $data_source: $DBI::errstr";

# This procedure takes one input parameter. It adds 1 to the input
# parameter value and returns the new value.
$dbh->do(q/CREATE PROCEDURE PROC_RETURN_INPUT_PARAM (@inputval int) AS
          SET @inputval = @inputval+1;
          RETURN @inputval;/);

# The first placeholder (?) in this prepared statement is used to
# capture the return value of the called procedure. The second
# placeholder represents the value that's supplied as the procedure's
# input parameter.
my $sth1 = $dbh->prepare ("{? = call PROC_RETURN_INPUT_PARAM(?) }");

my $output;

my $i = 1;

# Bind value for the first placeholder. Because the prepared statement
# updates the bind value, bind_param_inout rather than bind_param needs
# to be used.
$sth1->bind_param_inout(1, \$output, 1);

# Bind value for second placeholder. This is value for the procedure's
# input parameter.
$sth1->bind_param(2, $i);

# Execute the prepared statement.
$sth1->execute();

# Output the procedure's return value.
print "$output\n";

$dbh->do(q/DROP PROCEDURE PROC_RETURN_INPUT_PARAM/);

$dbh->disconnect;
This example script inserts rows into a table with an identity column and uses @@IDENTITY to display the identity value used in each new row. The identity value is a unique, incremental value that SQL Server automatically generates when a new row is added to the table.
The procedure in the script accepts one input parameter: a value to insert into the new row. The procedure returns the row's identity value.
#!/usr/bin/perl -w
use strict;

use DBI;

# Replace datasource_name with the name of your data source.
# Replace database_username and database_password
# with the SQL Server database username and password.
my $data_source = q/dbi:ODBC:datasource_name/;
my $user = q/database_username/;
my $password = q/database_password/;
my $dbh = DBI->connect($data_source, $user, $password)
    or die "Can't connect to $data_source: $DBI::errstr";

# Create sample table in which to insert test data. The first column is an
# identity column. When a new row is added to the table, SQL Server
# provides a unique, incremental value for the column so long as that
# column value is not specified.
$dbh->do(q/CREATE TABLE PERL_SAMPLE_TABLE (a INTEGER identity, b CHAR(1))/);

$dbh->do(q/CREATE PROCEDURE PROC_LAST_INSERTED_VALUE (@inputval char) AS
          INSERT INTO PERL_SAMPLE_TABLE VALUES (@inputval);
          RETURN @@IDENTITY;/);

# The first placeholder (?) in this prepared statement is used to
# capture the return value of the called procedure. The second
# placeholder represents the value that's supplied as the procedure's
# input parameter.
my $sth1 = $dbh->prepare ("{? = call PROC_LAST_INSERTED_VALUE(?) }");

my $output = 0;

my $char = q/a/;

# Insert two records into the table.
while ($char ne q/c/) {
   # Bind value for the first placeholder. Because the prepared statement
   # updates the bind value, bind_param_inout rather than bind_param needs
   # to be used.
   $sth1->bind_param_inout(1, \$output, 100);

   # Bind value for second placeholder. This is value for the procedure's
   # input parameter.
   $sth1->bind_param(2, $char);

   # Execute the prepared statement.
   $sth1->execute();

   # Display the last generated identity value.
   print "Identity value for last record = $output\n" if ($output != 0);

   $char++;
}

$dbh->do(q/DROP PROCEDURE PROC_LAST_INSERTED_VALUE/);
$dbh->do(q/DROP TABLE PERL_SAMPLE_TABLE/);

$dbh->disconnect;

Output Parameters

A procedure can return information by using either RETURN or output parameters. RETURN lets you return an integer value. Output parameters let you return other types of values from a procedure. For example, character strings and cursors.
Output parameters also let you return more than one value from a procedure. For example, in a procedure that contains multiple INSERT statements, you can use multiple output parameters to capture and return the numbers of rows affected by each statement.
The following sample script illustrates this technique. It uses output parameters to generate a cumulative total of the number of rows affected by statements in a procedure. The script contrasts this total with the one returned by the DBI rows method. The rows method returns the number of rows affected by the last row affecting statement. It's unaware that the example procedure contains more than one INSERT statement. The totals are different therefore. Note that this comment also applies to UPDATE and DELETE statements.
#!/usr/bin/perl -w
use strict;

use DBI;


# Replace datasource_name with the name of your data source.
# Replace database_username and database_password
# with the SQL Server database username and password.

my $data_source = q/dbi:ODBC:datasource_name/;
my $user = q/database_username/;
my $password = q/database_password/;
my $dbh = DBI->connect($data_source, $user, $password)
       or die "Can't connect to $data_source: $DBI::errstr";


# Create sample table in which to insert test data.

$dbh->do(q/CREATE TABLE PERL_SAMPLE_TABLE (i INTEGER)/);


# This procedure takes one input parameter and two output parameters.
# The procedure inserts the input parameter value into a test table.
# The output parameters are used to return the number of rows affected
# by each INSERT statement.
$dbh->do(q/CREATE PROCEDURE PROC_INSERT_TABLES (@inputval int,
                                                @rowcount1 int OUTPUT,
                                                @rowcount2 int OUTPUT) AS
    BEGIN

    -- SET NOCOUNT ON here will prevent DBI rows from returning
    -- the row count.

    INSERT INTO PERL_SAMPLE_TABLE VALUES (@inputval);

    -- @@ROWCOUNT returns the number of rows affected by the
    -- last statement. Store this number in the first output
    -- parameter.

 SET @rowcount1 = @@ROWCOUNT;
        INSERT INTO PERL_SAMPLE_TABLE VALUES (@inputval + 1);
 SET @rowcount2 = @@ROWCOUNT;
    END/);


# The first placeholder (?) in this prepared statement represents
# the value that's supplied as the procedure's input parameter.
# The second and third placeholders are used to capture the
# procedure's output parameter values.

my $sth1 = $dbh->prepare ("{call PROC_INSERT_TABLES(?, ?, ?)}");

my $i = 1;
my $sqlserverrowcount;
my $sqlserverrowcount2;


# Bind value for the first placeholder (the procedure's input parameter).
$sth1->bind_param(1, $i);


# $sqlserverrowcount and $sqlserverrowcount2 store the row count
# values returned by the procedure's output parameters.
$sth1->bind_param_inout(2, \$sqlserverrowcount, 1);
$sth1->bind_param_inout(3, \$sqlserverrowcount2, 1);


# Execute the prepared statement.
$sth1->execute();

# Produce a cumulative total for the number of rows affected
# by both INSERT statements.
$sqlserverrowcount = $sqlserverrowcount + $sqlserverrowcount2;

print "Rows affected (Cumulative \@ROWCOUNT) = $sqlserverrowcount\n";


# The rows method returns the number of rows affected by the last
# row affecting statement. It's unaware that the procedure contained
# more than one INSERT statement.
print "Rows affected (DBI rows method) = ", $sth1->rows, "\n";

$dbh->do(q/DROP PROCEDURE PROC_INSERT_TABLES/);
$dbh->do(q/DROP TABLE PERL_SAMPLE_TABLE/);

$dbh->disconnect;
Typical output from the above script is:
Rows affected (Cumulative @ROWCOUNT) = 2
Rows affected (DBI rows method) = 1
Note It is common practice to put "SET NOCOUNT ON" at the front of procedures, as this prevents DONE_IN_PROC TDS messages and speeds up procedures. If you do this, the DBI rows method will return -1, because the SQL Server ODBC driver does not get the count. The procedure in the example gets around this problem, as @@ROWCOUNT is still set.

Procedures Generating Multiple Result-Sets

Procedures can contain multiple SELECT statements. They are therefore capable of generating an unknown number of result sets. The following script shows how to handle multiple result set generating statements by using the boolean DBD::ODBC method odbc_more_results.
odbc_more_results lets your script check whether there is another result-set to be fetched. It returns false when no more results are available.
Note also that output parameters are not returned until odbc_more_results returns false.
To determine whether to return true or false, odbc_more_results calls SQLMoreResults. There are some situations where DBD::ODBC will automatically call SQLMoreResults without the need for odbc_more_results. If the previous SQL statement that executed was a non result-set generating statement, such as an INSERT statement, DBD::ODBC calls SQLMoreResults for you. This triggers the execution of the next statement in the procedure. If the previous statement generated a result set, your script needs to call SQLMoreResults explicitly by using odbc_more_results.
For example in the sample procedure, the first SELECT statement gets executed as a result of DBD::ODBC calling SQLMoreResults:
INSERT INTO PERL_SAMPLE_TABLE VALUES (@inputval);
SELECT i FROM PERL_SAMPLE_TABLE;
SELECT i FROM PERL_SAMPLE_TABLE WHERE i = @inputval;
SELECT @result = i FROM PERL_SAMPLE_TABLE WHERE i = @inputval;
The second and third SELECT statements get executed as a result of the script calling SQLMoreResults by using odbc_more_results.
#!/usr/bin/perl -w
use strict;

use DBI;


# Replace datasource_name with the name of your data source.
# Replace database_username and database_password
# with the SQL Server database username and password.

my $data_source = q/dbi:ODBC:datasource_name/;
my $user = q/database_username/;
my $password = q/database_password/;
my $dbh = DBI->connect($data_source, $user, $password)
    or die "Can't connect to $data_source: $DBI::errstr";

$dbh->do(q/CREATE TABLE PERL_SAMPLE_TABLE (i INTEGER)/);

$dbh->do(q/CREATE PROCEDURE PROC_MULTIPLE_RESULT_SETS (@inputval int,
             @result int OUTPUT) AS
  BEGIN
  -- Insert the input parameter value into the test table.
  INSERT INTO PERL_SAMPLE_TABLE VALUES (@inputval);
  SELECT i FROM PERL_SAMPLE_TABLE;
  SELECT i FROM PERL_SAMPLE_TABLE WHERE i = @inputval;
  -- This SELECT statement returns one value. Capture
  -- the value with the procedure's output parameter.
         SELECT @result = i FROM PERL_SAMPLE_TABLE
  WHERE i = @inputval;
  END /);

my $sth1 = $dbh->prepare ("{call PROC_MULTIPLE_RESULT_SETS(?, ?)}");

my $i = 1;
my $output = 0;

while ($i < 4) {
    print "Iteration $i\n";
    print "============\n";

    $sth1->bind_param(1, $i);
    $sth1->bind_param_inout(2, \$output, 100);

    $sth1->execute();
    print "  Rows affected: ", $sth1->rows, "\n";

    # The execute will cause the insert in the procedure to insert a
    # $i into the table. DBD::ODBC will spot this is not a result-set
    # generating statement and call the ODBC API SQLMoreResults for you
    # thus causing the first select to run.
    #

    my $rs=1;
    do {

 # Fetch and display the result sets generated by the first two
 # SELECT statements in the procedure.

 print "  result-set ", $rs++, ":\n";
 while (my (@row) = $sth1->fetchrow_array) {
     print "\t", join (", ", @row) , "\n";
 }
 print "  (calling SQLMoreResults)\n";
    } while ($sth1->{odbc_more_results}); # Check to see if there's more
                                          # data to be fetched.

    # All result sets have been retrieved. The procedure will now
    # have returned the output parameter value.

    print "  result-set ", $rs++, "\n\t$output\n" if ($output != 0);

    $i++;
    print "\n";
}

$dbh->do(q/DROP PROCEDURE PROC_MULTIPLE_RESULT_SETS/);
$dbh->do(q/DROP TABLE PERL_SAMPLE_TABLE/);

$dbh->disconnect;
Typical output from the above script is:
Iteration 1
============
  Rows affected: 1
  result-set 1:
        1
  (calling SQLMoreResults)
  result-set 2:
        1
  (calling SQLMoreResults)
  result-set 3
        1

Iteration 2
============
  Rows affected: 1
  result-set 1:
        1
        2
  (calling SQLMoreResults)
  result-set 2:
        2
  (calling SQLMoreResults)
  result-set 3
        2

Iteration 3
============
  Rows affected: 1
  result-set 1:
        1
        2
        3
  (calling SQLMoreResults)
  result-set 2:
        3
  (calling SQLMoreResults)
  result-set 3
        3

PRINT Statement and Status Messages

PRINT statements let you return a user-defined message from a procedure. They help you troubleshoot a procedure. For example, PRINT statements let you check data values or embed trace messages to isolate problem areas in a procedure.
To capture PRINT statement output in a Perl script, you need to create a custom error handler. The standard ODBC diagnostic mechanism does not retrieve PRINT statement output.
SQL Server commands such as BACKUP and DBCC also generate status messages to report their progress. You also need to create an error handler if you want to intercept these messages.
To replace the default error handler, set the odbc_err_handler database handle attribute to a reference to a subroutine that will act as the replacement error handler. The following script shows you how to do this.
#!/usr/bin/perl -w
use strict;

use DBI;
# Replace datasource_name with the name of your data source.
# Replace database_username and database_password
# with the SQL Server database username and password.
my $data_source = q/dbi:ODBC:datasource_name/;
my $user = q/database_username/;
my $password = q/database_password/;
my $dbh = DBI->connect($data_source, $user, $password)
    or die "Can't connect to $data_source: $DBI::errstr";

# Catch and display status messages with this error handler.
sub err_handler {
   my ($sqlstate, $msg, $nativeerr) = @_;
   # Strip out all of the driver ID stuff
   $msg =~ s/^(\[[\w\s:]*\])+//;
   print $msg;
   print "===> state: $sqlstate msg: $msg nativeerr: $nativeerr\n";
   return 0;
}

$dbh->{odbc_err_handler} = \&err_handler;

$dbh->{odbc_exec_direct} = 1;

my $sql = q/CREATE PROCEDURE PROC_PRINT_MESSAGES AS
           PRINT 'START';
           SELECT 1;
           PRINT 'END';/;

$dbh->do($sql);
my $sth = $dbh->prepare("{ call PROC_PRINT_MESSAGES  }");
$sth->execute;
do {
    while (my @row = $sth->fetchrow_array) {
       if ($row[0] eq 1) {
          print "Valid select results with print statements\n";
       }
    }
} while ($sth->{odbc_more_results});

$dbh->do(q/drop procedure PROC_PRINT_MESSAGES/);

$dbh->disconnect;
The following line in the script forces DBD::ODBC to use SQLExecDirect instead of SQLPrepare then SQLExecute.
$dbh->{odbc_exec_direct} = 1;
This prevents certain versions of the Windows MS SQL Server ODBC driver (you use this driver if you are using the ODBC-ODBC Bridge to access SQL Server) from generating errors when the procedure the script contains is executed. The errors are similar to the following:
(SQL-42S02)(DBD: Execute immediate failed err=-1) at 
myscript.pl line 6. DBD::ODBC::st execute failed: 
[Microsoft][ODBC SQL Server Driver]Invalid cursor state 
(SQL-24000)(DBD: dbd_describe/SQLNumResultCols err=-1) at 
myscript.pl line 12. DBD::ODBC::st fetchrow_array failed: 
(DBD: no select statement currently executing err=-1) at 
myscript.pl line 14.

Multiple Active Statements

In SQL Server 2005 and later, there is a feature called MARS (Multiple Active Result Sets), which allows multiple active SELECT statements. If you are using our SQL Server ODBC driver and want to use MARS, add this line to your SQL Server data source in odbc.ini:
Mars_Connection = Yes
Alternatively, add "MARS_Connection=Yes" to the connection string. For example:
my $dbh = DBI->connect("dbi:ODBC:DSN=$data_source;MARS_Connection=Yes;")
    or die "Can't connect to $data_source: $DBI::errstr";
Using this method will also enable MARS on the connection if you are connecting to SQL Server 2005+ with the Microsoft SQL Server Native Client ODBC driver via the ODBC-ODBC Bridge.
Microsoft SQL Server 2000 and earlier can support Multiple Active Statements if you use a server side cursor. If your version of either SQL Server or the Microsoft SQL Server ODBC driver does not support MARS, and you have no alternative other than to use Multiple Active Statements, you can enable this workaround by:
  • Setting setting SQL_ROWSET_SIZE to a value > 1 in your connect method. For example:
    my $dbh = DBI->connect("dbi:ODBC:$data_source", $user, $password)
        or die "Can't connect to $data_source: $DBI::errstr";
    $dbh->{odbc_SQL_ROWSET_SIZE} = 2;
    
  • Setting the cursor type to SQL_CURSOR_DYNAMIC in your connect method. For example:
    my $dbh = DBI->connect("dbi:ODBC:$data_source", $user, $password,
                           {odbc_cursortype => 2})
        or die "Can't connect to $data_source: $DBI::errstr";
    
The following script shows how to enable MARS from DBD::ODBC and provides workarounds for SQL Server 2000 and earlier, if you have no alternative other than to use Multiple Active Statements.
#!/usr/bin/perl -w
use strict;

use DBI;

#
# MS SQL Server does not by default allow Multiple Active Statements
# i.e. it does not allow you to create a second result set on another
# statement whilst a result-set is active on another statement.
# In MS SQL Server 2005 and later, there is a feature called Multiple
# Active Result Sets (MARS), which allows multiple active SELECT
# statements, but has some implications if you are also doing transactions.
# (See http://msdn.microsoft.com/en-us/library/ms345109.aspx.)
# To enable MARS from DBD::ODBC, add "MARS_Connection=Yes"
# to the connection string as in:
#
#  DBI->connect('dbi:ODBC:DSN=mydsn;MARS_Connection=Yes;');
#
# MS SQL Server 2000 and earlier can support Multiple Active Statements
# if you use a server side cursor, but the normal ways of enabling server
# side cursors are not available in DBD::ODBC. A workaround was found by
# setting SQL_ROWSET_SIZE to a value > 1. However,
# a) although this persuades MS SQL Server to create a server side cursor
#    server-side cursors are slower than static cursors.
# b) it is slightly dangerous, as if you do not consume all the result-set
#    or call finish, you can hang the MS SQL Server ODBC driver.
#    This is easily demonstrated via the PHP interface
#    /developer/languages/php/apache_odbc.html#appb2 but
#    we have never reproduced it in DBD::ODBC - perhaps because finish
#    is called for you.
# c) this workaround only works because DBD::ODBC does not use
#    SQLExtendedFetch - if that changed it would undoubtably break.
#
# A more reliable way of doing this is by setting the cursor type
# to SQL_CURSOR_DYNAMIC. You can do this in the connect method
# as below.

my $data_source = q/datasource_name/;
my $user = q/database_username/;
my $password = q/database_password/;

# Use this form of connect to get multiple active statements
# in SQL Server 2005 and later:
#
my $dbh = DBI->connect("dbi:ODBC:DSN=$data_source;MARS_Connection=Yes;")
    or die "Can't connect to $data_source: $DBI::errstr";

#
# SQL Server 2000 and earlier:
#
#my $dbh = DBI->connect("dbi:ODBC:$data_source", $user, $password,
#                       {odbc_cursortype => 2})
#    or die "Can't connect to $data_source: $DBI::errstr";

# Alternative method to get MAS for SQL Server 2000 and earlier:
#
# Uncomment the next line to use the workaround to get MAS.
# Better method is to use odbc_cursor_type.
#
#$dbh->{odbc_SQL_ROWSET_SIZE} = 2;

$dbh->do(q/create table "mas" (a integer)/);
$dbh->do(q/create table "mas2" (a integer)/);
$dbh->do(q/insert into "mas" values (1)/);
$dbh->do(q/insert into "mas2" values (2)/);

my $sth = $dbh->prepare(q/select * from "mas"/);

# If you are connecting to SQL Server 2000 or earlier and have not
# done one of the following:
#
#  a) Set a dynamic cursor (see first commented out connect
#     call, above).
#
#  b) Uncommented the SQL_ROWSET_SIZE workaround (see commented
#     out code above) then you will get an error similar to:
#
# "DBD::ODBC::st execute failed: [unixODBC][Microsoft
# [SQL Native Client] Connection is busy with results for
# another command (SQL-HY000) at mas.pl line 92."
#
# You also need to use one of these workarounds if you are using a
# non-SQL Native Client version of the Microsoft SQL Server ODBC
# driver.

$sth->execute;

my $sth2 = $dbh->prepare(q/select * from "mas2"/);

$sth2->execute;

my $col = $sth->fetchrow_array;
print "Column from first result-set, val = $col\n";
my $othercol = $sth2->fetchrow_array;
print "Column from second result-set, val = $othercol\n";

$sth->finish;
$sth2->finish;

$dbh->do(q/drop table "mas"/);
$dbh->do(q/drop table "mas2"/);

$dbh->disconnect;

Faster Inserting

These examples use a table containing 5 columns: an integer, a char(30), a varchar(255), a timestamp and a float.
The simplest code to populate this table is:
my $sql;
for (my $i = 0; $i <50000; $i++) {
    sql = "insert into perf values (" . $i . ", 'this is a char thirty'" .
           ",'this is a varchar 255', {ts '2008-08-01 11:12:13.123'}, "
    . $i * 1.1 . ")";
    my $sth = $dbh->prepare($sql);
    $sth->execute;
}
Here we construct the SQL insert statement once for each row, and call SQLExecDirect once for each row. The problem with this code is that the database has to parse and prepare the insert statement once per row; this can be time consuming.
A much more efficient method is to use a parameterized insert. Here, parameters are using in place of the column data. Instead of the SQL shown above, we would use:
insert into perf values (?,?,?,?,?)
We prepare this SQL once (using the prepare method), bind the parameters with the bind_param method, and then just keep calling the execute method. For some columns, we change the data bound each time. For example:
my $sth = $dbh->prepare(q/insert into perf values (?,?,?,?,?)/);

$sth->bind_param(2, 'this is a char thirty');
$sth->bind_param(3, 'this is a varchar 255');
$sth->bind_param(4, '2008-08-01 11:12:13.123');

for (my $i = 0; $i < 50000; $i++)
{
    $sth->bind_param(1, $i);
    $sth->bind_param(5, $i*1.1);
    $sth->execute;
}
Another change we could make is to use arrays of parameters but doing this does not seem to make any real difference to performance.

Alternative Perl SQL Server Solution

The ODBC-ODBC Bridge is another solution from Easysoft that provides Perl to SQL Server connectivity from UNIX and Linux platforms.
The ODBC-ODBC Bridge is available on more platforms than our SQL Server ODBC driver.
The ODBC-ODBC Bridge is an ODBC driver for UNIX and Linux that accesses MS SQL Server by using the Windows MS SQL Server ODBC driver.
The components necessary to provide ODBC access to Microsoft SQL Server data from Perl on UNIX and Linux platforms.

What You Need to Install

The ODBC-ODBC Bridge allows ODBC applications on one machine to access ODBC drivers on a remote machine.
The ODBC-ODBC Bridge consists of a client ODBC driver (which you install on the machine where Perl is running) and a server (which you install on a Windows machine where the Microsoft SQL Server ODBC driver is installed).
Refer to the following example to see what you need to install on your client and server machines:
  • Client Machine This is the machine where you want to run your Perl. You need to have installed:
    • Perl The minimum version required for Perl’s DBI module.
    • Perl DBI. The database independent interface for Perl. You can get this from CPAN.
    • Perl DBD::ODBC. The ODBC driver for DBI. You can get this from CPAN. There are other ways of accessing MS SQL Server from Perl such as the XML-ODBC Server, but this tutorial concerns itself with DBI/DBD::ODBC.
    • The ODBC-ODBC Bridge Client The ODBC-ODBC Bridge Client is an ODBC driver that talks to the ODBC-ODBC Bridge Server and therefore your remote ODBC data source. You need to install the ODBC-ODBC Bridge Client and the unixODBC Driver Manager. ODBC-ODBC Bridge distributions include the unixODBC Driver Manager. There is no need to install the ODBC-ODBC Bridge Server on this machine. Refer to the ODBC-ODBC Bridge manual for installation instructions.
    For help on installing Perl DBI, DBD::ODBC and the ODBC-ODBC Bridge client see Enabling ODBC support in Perl with Perl DBI and DBD::ODBC.
  • Server machine This is the machine where you have (or can install) an ODBC driver for the database you want to access. You need to have installed:
    • ODBC driver For this tutorial, you need the Microsoft SQL Server ODBC driver, and it is available in Microsoft Data Access Components (MDAC), the Microsoft SQL Server Native Client and the Microsoft SQL Server 2008 Native Client. You do not need install the MS SQL Server ODBC driver on the same machine as your SQL Server database.
    • The ODBC-ODBC Bridge Server. The ODBC-ODBC Bridge Server is an ODBC application, which accepts connections from the ODBC-ODBC Bridge Client and relays them to your target ODBC data source. You need to license the ODBC-ODBC Bridge Server, and trial licenses may be obtained during the installation. Refer to the ODBC-ODBC Bridge manual for installation instructions. In the following sections, we refer to the Server machine as windows_server.

Data Sources

You will find a lot of very useful information on ODBC connection attributes and data sources in DBD::ODBC Tutorial Part 1 - Drivers, Data Sources and Connection.
An ODBC data source is a named resource that the application passes to the ODBC driver manager. The data source tells the driver manager which ODBC driver to load and which connection attributes to use. You do not have to create data sources, as DSN-less connections provide an alternative way to connect, and you will find details on this in the first tutorial.
With the ODBC-ODBC Bridge, there are two data sources to consider. The first data source is an ODBC-ODBC Bridge Client one on your client machine. This data source tells the driver manager to use the ODBC-ODBC Bridge Client and sets a number of attributes for the ODBC-ODBC Bridge Client. The attributes tell the ODBC-ODBC Bridge Client which server to connect to and which data source on the remote machine to use.
A typical ODBC-ODBC Bridge Client data source looks like this:
[mydatasource]
# Driver tells the driver manager which ODBC driver to use
Driver = ODBC-ODBC Bridge
# Description is a description of this data source
Description = connect to SQL Server on windows
# ServerPort is the name of the machine where the ODBC-ODBC Bridge Server is running
# and the port on which it is listening. The default port is 8888.
ServerPort = windows_server:8888

# LogonUser is a valid user account on the windows_server machine
# LogonAuth is LogonUser's password
LogonUser = my_windows_username
LogonAuth = LogonUsers_password

# TargetDSN is the name of the data source on windows_server to connect to
TargetDSN = windows_server_dsn
# TargetUser and TargetAuth are synonomous with the ODBC connection
# attributes UID and PWD and specify the user and password to use for
# the database login - if required.
#
TargetUser = db_username
TargetAuth = TargetUsers_password
We will describe these attributes in the following sections. When using Perl DBI, you do not need to specify TargetUser and TargetAuth in the data source, as these are passed in to the DBI->connect method.

Authentication

There are two levels of authentication you need to be aware of:
  1. ODBC-ODBC Bridge Server authentication By default, the ODBC-ODBC Bridge Server needs to authenticate the client and become the specified user on the windows_server machine. To do this, the ODBC-ODBC Bridge Client needs to specify the data source attributes LogonUser and LogonAuth. LogonUser is the name of a user who has permission to log on locally to the windows_server machine and LogonAuth is that user’s password. A user who has log on locally permissions is defined as a user who can log on at the console of windows_server. If LogonUser and LogonAuth are valid, the ODBC-ODBC Bridge Server becomes the LogonUser.
    Note You can turn off ODBC-ODBC Bridge Server authentication, but this has various implications (see the ODBC-ODBC Bridge manual).
  2. MS SQL Server authentication When you create a MS SQL Server data source in the Windows ODBC Administrator, you have the choice of:
    • With Integrated Windows authentication This is sometimes called trusted connections. In this situation, MS SQL Server examines the user on the Windows machine that is communicating with it and no SQL Server user name or password are required.
    • With SQL Server authentication using a login ID and password entered by the user In this scenario, MS SQL Server requires a database user name and password that your database administrator will have set up. If this is your situation, the ODBC connection attributes UID and PWD must be specified at the client end (you do this with the second and third arguments to DBI->connect).
At this stage, an example might help illustrate SQL Server authentication. Suppose you have an account on the windows_server machine; your username is "Fred Bloggs" and your password is "mypassword". Your database administrator has set up the SQL Server instance with SQL Server authentication active, and has set you up an account for the database with username "dbuser" and password "dbpassword". You need to set the OOB data source attributes LogonUser/LogonAuth to "Fred Bloggs" and "mypassword" and call DBI->connect with "dbuser"/"dbpassword".

ServerPort

The ServerPort attribute tells the ODBC-ODBC Bridge Client ODBC driver which server to connect to. ServerPort is the name or IP address of the server machine where the ODBC-ODBC Bridge Server Service is running and the port the Server is listening on. The port defaults to 8888 in the ODBC-ODBC Bridge Server configuration. This is not the port your database engine is listening on. Separate the server machine from the port with a colon (:) in the ServerPort attribute value. For example, windows_server:8888.
The ODBC-ODBC Bridge Server is configurable through an HTTP interface. Supposing your ODBC-ODBC Bridge Server is installed on windows.mycompany.local, you can access the ODBC-ODBC Bridge Server administration interface using the URL http://windows.mycompany.local:8890.
Note On Windows, the ODBC-ODBC Bridge Server installation sets the HTTP interface port to 8890, by default. This default setting can be changed during the ODBC-ODBC Bridge server installation and through the HTTP interface’s Configuration section.

Target Data Source

The TargetDSN attribute tells the ODBC-ODBC Bridge Client which data source on the remote server you want to access. This must be the name of a System data source as the ODBC-ODBC Bridge Server can only access System data sources. (To create a System data source, in the Microsoft ODBC Administrator, select the System DSN tab before clicking on Add).
For more information about creating a System DSN on Windows, see the ODBC-ODBC Bridge manual.

Easy Way to Handle Android Notifications

Android Notifications Android Toast class provides a handy way to show users alerts but problem is that these alerts are not persist...