| Win32-ODBC documentation | Contained in the Win32-ODBC distribution. |
Win32::ODBC - ODBC Extension for Win32
To use this module, include the following statement at the top of your script:
use Win32::ODBC;
Next, create a data connection to your DSN:
$Data = new Win32::ODBC("MyDSN");
NOTE: MyDSN can be either the DSN as defined in the ODBC Administrator, or it can be an honest-to-God DSN Connect String.
Example: "DSN=My Database;UID=Brown Cow;PWD=Moo;"
You should check to see if $Data is indeed defined, otherwise there
has been an error.
You can now send SQL queries and retrieve info to your heart's content! See the description of the methods provided by this module below and also the file TEST.PL as referred to in INSTALLATION NOTES to see how it all works.
Finally, MAKE SURE that you close your connection when you are finished:
$Data->Close();
This is a hack of Dan DeMaggio's <dmag@umich.edu> NTXS.C ODBC implementation. I have recoded and restructured most of it including most of the ODBC.PM package, but its very core is still based on Dan's code (thanks Dan!).
The history of this extension is found in the file HISTORY.TXT that comes with the original archive (see INSTALLATION NOTES below).
And what are the benefits of this module?
This package defines a number of constants. You may refer to each of
these constants using the notation ODBC::xxxxx, where xxxxx is
the constant.
Example:
print ODBC::SQL_SQL_COLUMN_NAME, "\n";
For the method documentation that follows, an * following the method parameters indicates that that method is new or has been modified for this version.
Creates a new ODBC connection based on DSN, or, if you specify an
already existing ODBC object, then a new ODBC object will be created
but using the ODBC Connection specified by ODBC_OBJECT. (The new
object will be a new hstmt using the hdbc connection in
ODBC_OBJECT.)
DSN is Data Source Name or a proper ODBCDriverConnect string.
You can specify SQL Connect Options that are implemented before the
actual connection to the DSN takes place. These option/values are the
same as specified in GetConnectOption/SetConnectOption (see
below) and are defined in the ODBC API specs.
Returns a handle to the database on success, or undef on failure.
Tells ODBC to create a data set that contains table information about
the DSN. Use Fetch and Data or DataHash to retrieve the data.
The returned format is:
[Qualifier] [Owner] [Name] [Type]
Returns true on error.
Returns the attribute ATTRIBUTE on each of the fields in the list
FIELD_NAMES in the current record set. If FIELD_NAMES is empty,
then all fields are assumed. The attributes are returned as an
associative array.
Configures a DSN. OPTION takes on one of the following values:
ODBC_ADD_DSN.......Adds a new DSN.
ODBC_MODIFY_DSN....Modifies an existing DSN.
ODBC_REMOVE_DSN....Removes an existing DSN.
ODBC_ADD_SYS_DSN.......Adds a new System DSN.
ODBC_MODIFY_SYS_DSN....Modifies an existing System DSN.
ODBC_REMOVE_SYS_DSN....Removes an existing System DSN.
You must specify the driver DRIVER (which can be retrieved by using
DataSources or Drivers).
ATTRIBUTE1 should be "DSN=xxx" where xxx is the name of
the DSN. Other attributes can be any DSN attribute such as:
"UID=Cow"
"PWD=Moo"
"Description=My little bitty Data Source Name"
Returns true on success, false on failure.
NOTE 1: If you use ODBC_ADD_DSN, then you must include at least
"DSN=xxx" and the location of the database.
Example: For MS Access databases, you must specify the DatabaseQualifier:
"DBQ=c:\\...\\MyDatabase.mdb"
NOTE 2: If you use ODBC_MODIFY_DSN, then you need only specify
the "DNS=xxx" attribute. Any other attribute you include will be
changed to what you specify.
NOTE 3: If you use ODBC_REMOVE_DSN, then you need only specify
the "DSN=xxx" attribute.
Returns the connection number associated with the ODBC connection.
Closes the ODBC connection. No return value.
Returns the contents of column name FIELD_NAME or the current row
(if nothing is specified).
Returns the contents for FIELD1, FIELD2, ... or the entire row (if
nothing is specified) as an associative array consisting of:
{Field Name} => Field Data
Returns an associative array of Data Sources and ODBC remarks about them. They are returned in the form of:
$ArrayName{'DSN'}=Driver
where DSN is the Data Source Name and ODBC Driver used.
Sets the debug option to on or off. If nothing is specified, then nothing is changed.
Returns the debugging value (1 or 0).
Returns an associative array of ODBC Drivers and their attributes. They are returned in the form of:
$ArrayName{'DRIVER'}=Attrib1;Attrib2;Attrib3;...
where DRIVER is the ODBC Driver Name and AttribX are the driver-defined attributes.
Drops the cursor associated with the ODBC object. This forces the
cursor to be deallocated. This overrides SetStmtCloseType, but the
ODBC object does not lose the StmtCloseType setting. CLOSE_TYPE
can be any valid SmtpCloseType and will perform a close on the stmt
using the specified close type.
Returns true on success, false on failure.
Dumps to the screen the fieldnames and all records of the current data set. Used primarily for debugging. No return value.
Returns the last encountered error. The returned value is context dependent:
If called in a scalar context, then a 3-element array is returned:
( ERROR_NUMBER, ERROR_TEXT, CONNECTION_NUMBER )
If called in a string context, then a string is returned:
"[ERROR_NUMBER] [CONNECTION_NUMBER] [ERROR_TEXT]"
If debugging is on then two more variables are returned:
( ..., FUNCTION, LEVEL )
where FUNCTION is the name of the function in which the error
occurred, and LEVEL represents extra information about the error
(usually the location of the error).
Retrieves the next record from the keyset. When ROW and/or TYPE
are specified, the call is made using SQLExtendedFetch instead of
SQLFetch.
NOTE 1: If you are unaware of SQLExtendedFetch and its
implications, stay with just regular FetchRow with no parameters.
NOTE 2: The ODBC API explicitly warns against mixing calls to
SQLFetch and SQLExtendedFetch; use one or the other but not
both.
If ROW is specified, it moves the keyset RELATIVE ROW number
of rows.
If ROW is specified and TYPE is not, then the type used is
RELATIVE.
Returns true when another record is available to read, and false when there are no more records.
Returns an array of fieldnames found in the current data set. There is no guarantee on order.
Returns an array of connection numbers showing what connections are currently open.
Returns the value of the specified connect option OPTION. Refer to
ODBC documentation for more information on the options and values.
Returns a string or scalar depending upon the option specified.
Returns the name of the current cursor as a string or undef.
Retrieves the current row from the dataset. This is not generally used by users; it is used internally.
Returns an array of field data where the first element is either false (if successful) and true (if not successful).
Returns an associative array indicating the configuration for the specified DSN.
If no DSN is specified then the current connection is used.
The returned associative array consists of:
keys=DSN keyword; values=Keyword value. $Data{$Keyword}=Value
Returns an associative array indicating the ability of the ODBC Driver to support the specified functions. If no functions are specified, then a 100 element associative array is returned containing all possible functions and their values.
FUNCTION must be in the form of an ODBC API constant like
SQL_API_SQLTRANSACT.
The returned array will contain the results like:
$Results{SQL_API_SQLTRANSACT}=Value
Example:
$Results = $O->GetFunctions(
$O->SQL_API_SQLTRANSACT,
SQL_API_SQLSETCONNECTOPTION
);
$ConnectOption = $Results{SQL_API_SQLSETCONNECTOPTION};
$Transact = $Results{SQL_API_SQLTRANSACT};
Returns a string indicating the value of the particular option specified.
Returns the current allocated limit for MaxBufSize. For more info,
see SetMaxBufSize.
Returns a string indicating the SQL state as reported by ODBC. The SQL state is a code that the ODBC Manager or ODBC Driver returns after the execution of a SQL function. This is helpful for debugging purposes.
Returns a string indicating the type of closure that will be used
everytime the hstmt is freed. See SetStmtCloseType for details.
By default, the connection of the current object will be used. If
CONNECTION is a valid connection number, then it will be used.
Returns the value of the specified statement option OPTION. Refer
to ODBC documentation for more information on the options and values.
Returns a string or scalar depending upon the option specified.
This will report whether there is data yet to be retrieved from the query. This can happen if the query was a multiple select.
Example:
"SELECT * FROM [foo] SELECT * FROM [bar]"
NOTE: Not all drivers support this.
Returns 1 if there is more data, undef otherwise.
For UPDATE, INSERT and DELETE statements, the returned value is the number of rows affected by the request or -1 if the number of affected rows is not available.
NOTE 1: This function is not supported by all ODBC drivers! Some drivers do support this but not for all statements (e.g., it is supported for UPDATE, INSERT and DELETE commands but not for the SELECT command).
NOTE 2: Many data sources cannot return the number of rows in a result set before fetching them; for maximum interoperability, applications should not rely on this behavior.
Returns the number of affected rows, or -1 if not supported by the driver in the current context.
Executes the SQL command SQL and dumps to the screen info about it. Used primarily for debugging.
No return value.
Sets the value of the specified connect option OPTION. Refer to ODBC documentation for more information on the options and values.
Returns true on success, false otherwise.
Sets the name of the current cursor.
Returns true on success, false otherwise.
Moves the cursor to the row ROW within the current keyset (not
the current data/result set).
Returns true on success, false otherwise.
This sets the MaxBufSize for a particular connection. This will most likely never be needed but...
The amount of memory that is allocated to retrieve the field data of a record is dynamic and changes when it need to be larger. I found that a memo field in an MS Access database ended up requesting 4 Gig of space. This was a bit much so there is an imposed limit (2,147,483,647 bytes) that can be allocated for data retrieval.
Since it is possible that someone has a database with field data greater than 10,240, you can use this function to increase the limit up to a ceiling of 2,147,483,647 (recompile if you need more).
Returns the max number of bytes.
Sets a particular hstmt close type for the connection. This is the
same as ODBCFreeStmt(hstmt, TYPE). By default, the connection of
the current object will be used. If CONNECTION is a valid
connection number, then it will be used.
TYPE may be one of:
SQL_CLOSE
SQL_DROP
SQL_UNBIND
SQL_RESET_PARAMS
Returns a string indicating the newly set type.
Sets the value of the specified statement option OPTION. Refer to
ODBC documentation for more information on the options and values.
Returns true on success, false otherwise.
Closes the ODBC connection and dumps to the screen info about it. Used primarily for debugging.
No return value.
Executes the SQL command SQL_STRING on the current connection.
Returns ? on success, or an error number on failure.
Returns the catalog of tables that are available in the DSN. For an unknown parameter, just specify the empty string "".
Returns an array of table names.
Forces the ODBC connection to perform a rollback or commit transaction.
TYPE may be one of:
SQL_COMMIT
SQL_ROLLBACK
NOTE: This only works with ODBC drivers that support transactions. Your driver supports it if true is returned from:
$O->GetFunctions($O->SQL_API_SQLTRANSACT)[1]
(See GetFunctions for more details.)
Returns true on success, false otherwise.
Returns an array of version numbers for the requested packages
(ODBC.pm or ODBC.PLL). If the list PACKAGES is empty, then
all version numbers are returned.
What known problems does this thing have?
SQLConnection. I don't think that this is a problem with the code,
but more like a problem with ODBC. This happens because some ODBC
drivers need to write a temporary file. I noticed this using the MS
Jet Engine (Access Driver). If you wish to use this module with a build of Perl other than ActivePerl, you may wish to fetch the original source distribution for this module at:
ftp://ftp.roth.net:/pub/ntperl/ODBC/970208/Bin/Win32_ODBC_Build_CORE.zip
or one of the other archives at that same location. See the included README for hints on installing this module manually, what to do if you get a parse exception, and a pointer to a test script for this module.
Find a FAQ for Win32::ODBC at:
http://www.roth.net/odbc/odbcfaq.htm
Dave Roth <rothd@roth.net>
Based on original code by Dan DeMaggio <dmag@umich.edu>
I do not guarantee ANYTHING with this package. If you use it you are doing so AT YOUR OWN RISK! I may or may not support this depending on my time schedule.
Last Modified 1999.09.25.
Copyright (c) 1996-1998 Dave Roth. All rights reserved.
Courtesy of Roth Consulting: http://www.roth.net/consult/
Use under GNU General Public License. Details can be found at: http://www.gnu.org/copyleft/gpl.html
| Win32-ODBC documentation | Contained in the Win32-ODBC distribution. |
package Win32::ODBC; $VERSION = '0.034'; # Win32::ODBC.pm # +==========================================================+ # | | # | ODBC.PM package | # | --------------- | # | | # | Copyright (c) 1996, 1997 Dave Roth. All rights reserved. | # | This program is free software; you can redistribute | # | it and/or modify it under the same terms as Perl itself. | # | | # +==========================================================+ # # # based on original code by Dan DeMaggio (dmag@umich.edu) # # Use under GNU General Public License or Larry Wall's "Artistic License" # # Check the README.TXT file that comes with this package for details about # it's history. # require Exporter; require DynaLoader; $ODBCPackage = "Win32::ODBC"; $ODBCPackage::Version = 970208; $::ODBC = $ODBCPackage; $CacheConnection = 0; # Reserve ODBC in the main namespace for US! *ODBC::=\%Win32::ODBC::; @ISA= qw( Exporter DynaLoader ); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. @EXPORT = qw( ODBC_ADD_DSN ODBC_REMOVE_DSN ODBC_CONFIG_DSN ODBC_ADD_SYS_DSN ODBC_REMOVE_SYS_DSN ODBC_CONFIG_SYS_DSN SQL_DONT_CLOSE SQL_DROP SQL_CLOSE SQL_UNBIND SQL_RESET_PARAMS SQL_FETCH_NEXT SQL_FETCH_FIRST SQL_FETCH_LAST SQL_FETCH_PRIOR SQL_FETCH_ABSOLUTE SQL_FETCH_RELATIVE SQL_FETCH_BOOKMARK SQL_COLUMN_COUNT SQL_COLUMN_NAME SQL_COLUMN_TYPE SQL_COLUMN_LENGTH SQL_COLUMN_PRECISION SQL_COLUMN_SCALE SQL_COLUMN_DISPLAY_SIZE SQL_COLUMN_NULLABLE SQL_COLUMN_UNSIGNED SQL_COLUMN_MONEY SQL_COLUMN_UPDATABLE SQL_COLUMN_AUTO_INCREMENT SQL_COLUMN_CASE_SENSITIVE SQL_COLUMN_SEARCHABLE SQL_COLUMN_TYPE_NAME SQL_COLUMN_TABLE_NAME SQL_COLUMN_OWNER_NAME SQL_COLUMN_QUALIFIER_NAME SQL_COLUMN_LABEL SQL_COLATT_OPT_MAX SQL_COLUMN_DRIVER_START SQL_COLATT_OPT_MIN SQL_ATTR_READONLY SQL_ATTR_WRITE SQL_ATTR_READWRITE_UNKNOWN SQL_UNSEARCHABLE SQL_LIKE_ONLY SQL_ALL_EXCEPT_LIKE SQL_SEARCHABLE ); #The above are included for backward compatibility sub new { my ($n, $self); my ($type) = shift; my ($DSN) = shift; my (@Results) = @_; if (ref $DSN){ @Results = ODBCClone($DSN->{'connection'}); }else{ @Results = ODBCConnect($DSN, @Results); } @Results = processError(-1, @Results); if (! scalar(@Results)){ return undef; } $self = bless {}; $self->{'connection'} = $Results[0]; $ErrConn = $Results[0]; $ErrText = $Results[1]; $ErrNum = 0; $self->{'DSN'} = $DSN; $self; } #### # Close this ODBC session (or all sessions) #### sub Close { my ($self, $Result) = shift; $Result = DESTROY($self); $self->{'connection'} = -1; return $Result; } #### # Auto-Kill an instance of this module #### sub DESTROY { my ($self) = shift; my (@Results) = (0); if($self->{'connection'} > -1){ @Results = ODBCDisconnect($self->{'connection'}); @Results = processError($self, @Results); if ($Results[0]){ undef $self->{'DSN'}; undef @{$self->{'fnames'}}; undef %{$self->{'field'}}; undef %{$self->{'connection'}}; } } return $Results[0]; } sub sql{ return (Sql(@_)); } #### # Submit an SQL Execute statement for processing #### sub Sql{ my ($self, $Sql, @Results) = @_; @Results = ODBCExecute($self->{'connection'}, $Sql); return updateResults($self, @Results); } #### # Retrieve data from a particular field #### sub Data{ # Change by JOC 06-APR-96 # Altered by Dave Roth <dave@roth.net> 96.05.07 my($self) = shift; my(@Fields) = @_; my(@Results, $Results, $Field); if ($self->{'Dirty'}){ GetData($self); $self->{'Dirty'} = 0; } @Fields = @{$self->{'fnames'}} if (! scalar(@Fields)); foreach $Field (@Fields) { if (wantarray) { push(@Results, data($self, $Field)); } else { $Results .= data($self, $Field); } } return wantarray ? @Results : $Results; } sub DataHash{ my($self, @Results) = @_; my(%Results, $Element); if ($self->{'Dirty'}){ GetData($self); $self->{'Dirty'} = 0; } @Results = @{$self->{'fnames'}} if (! scalar(@Results)); foreach $Element (@Results) { $Results{$Element} = data($self, $Element); } return %Results; } #### # Retrieve data from the data buffer #### sub data { $_[0]->{'data'}->{$_[1]}; } sub fetchrow{ return (FetchRow(@_)); } #### # Put a row from an ODBC data set into data buffer #### sub FetchRow{ my ($self, @Results) = @_; my ($item, $num, $sqlcode); # Added by JOC 06-APR-96 # $num = 0; $num = 0; undef $self->{'data'}; @Results = ODBCFetch($self->{'connection'}, @Results); if (! (@Results = processError($self, @Results))){ #### # There should be an innocuous error "No records remain" # This indicates no more records in the dataset #### return undef; } # Set the Dirty bit so we will go and extract data via the # ODBCGetData function. Otherwise use the cache. $self->{'Dirty'} = 1; # Return the array of field Results. return @Results; } sub GetData{ my($self) = @_; my @Results; my $num = 0; @Results = ODBCGetData($self->{'connection'}); if (!(@Results = processError($self, @Results))){ return undef; } #### # This is a special case. Do not call processResults #### ClearError(); foreach (@Results){ s/ +$// if defined $_; # HACK $self->{'data'}->{ ${$self->{'fnames'}}[$num] } = $_; $num++; } # return is a hack to interface with a assoc array. return wantarray? (1, 1): 1; } #### # See if any more ODBC Results Sets # Added by Brian Dunfordshore <Brian_Dunfordshore@bridge.com> # 96.07.10 #### sub MoreResults{ my ($self) = @_; my(@Results) = ODBCMoreResults($self->{'connection'}); return (processError($self, @Results))[0]; } #### # Retrieve the catalog from the current DSN # NOTE: All Field names are uppercase!!! #### sub Catalog{ my ($self) = shift; my ($Qualifier, $Owner, $Name, $Type) = @_; my (@Results) = ODBCTableList($self->{'connection'}, $Qualifier, $Owner, $Name, $Type); # If there was an error return 0 else 1 return (updateResults($self, @Results) != 1); } #### # Return an array of names from the catalog for the current DSN # TableList($Qualifier, $Owner, $Name, $Type) # Return: (array of names of tables) # NOTE: All Field names are uppercase!!! #### sub TableList{ my ($self) = shift; my (@Results) = @_; if (! scalar(@Results)){ @Results = ("", "", "%", "TABLE"); } if (! Catalog($self, @Results)){ return undef; } undef @Results; while (FetchRow($self)){ push(@Results, Data($self, "TABLE_NAME")); } return sort(@Results); } sub fieldnames{ return (FieldNames(@_)); } #### # Return an array of fieldnames extracted from the current dataset #### sub FieldNames { $self = shift; return @{$self->{'fnames'}}; } #### # Closes this connection. This is used mostly for testing. You should # probably use Close(). #### sub ShutDown{ my($self) = @_; print "\nClosing connection $self->{'connection'}..."; $self->Close(); print "\nDone\n"; } #### # Return this connection number #### sub Connection{ my($self) = @_; return $self->{'connection'}; } #### # Returns the current connections that are in use. #### sub GetConnections{ return ODBCGetConnections(); } #### # Set the Max Buffer Size for this connection. This determines just how much # ram can be allocated when a fetch() is performed that requires a HUGE amount # of memory. The default max is 10k and the absolute max is 100k. # This will probably never be used but I put it in because I noticed a fetch() # of a MEMO field in an Access table was something like 4Gig. Maybe I did # something wrong, but after checking several times I decided to impliment # this limit thingie. #### sub SetMaxBufSize{ my($self, $Size) = @_; my(@Results) = ODBCSetMaxBufSize($self->{'connection'}, $Size); return (processError($self, @Results))[0]; } #### # Returns the Max Buffer Size for this connection. See SetMaxBufSize(). #### sub GetMaxBufSize{ my($self) = @_; my(@Results) = ODBCGetMaxBufSize($self->{'connection'}); return (processError($self, @Results))[0]; } #### # Returns the DSN for this connection as an associative array. #### sub GetDSN{ my($self, $DSN) = @_; if(! ref($self)){ $DSN = $self; $self = 0; } if (! $DSN){ $self = $self->{'connection'}; } my(@Results) = ODBCGetDSN($self, $DSN); return (processError($self, @Results)); } #### # Returns an associative array of $XXX{'DSN'}=Description #### sub DataSources{ my($self, $DSN) = @_; if(! ref $self){ $DSN = $self; $self = 0; } my(@Results) = ODBCDataSources($DSN); return (processError($self, @Results)); } #### # Returns an associative array of $XXX{'Driver Name'}=Driver Attributes #### sub Drivers{ my($self) = @_; if(! ref $self){ $self = 0; } my(@Results) = ODBCDrivers(); return (processError($self, @Results)); } #### # Returns the number of Rows that were affected by the previous SQL command. #### sub RowCount{ my($self, $Connection) = @_; if (! ref($self)){ $Connection = $self; $self = 0; } if (! $Connection){$Connection = $self->{'connection'};} my(@Results) = ODBCRowCount($Connection); return (processError($self, @Results))[0]; } #### # Returns the Statement Close Type -- how does ODBC Close a statment. # Types: # SQL_DROP # SQL_CLOSE # SQL_UNBIND # SQL_RESET_PARAMS #### sub GetStmtCloseType{ my($self, $Connection) = @_; if (! ref($self)){ $Connection = $self; $self = 0; } if (! $Connection){$Connection = $self->{'connection'};} my(@Results) = ODBCGetStmtCloseType($Connection); return (processError($self, @Results)); } #### # Sets the Statement Close Type -- how does ODBC Close a statment. # Types: # SQL_DROP # SQL_CLOSE # SQL_UNBIND # SQL_RESET_PARAMS # Returns the newly set value. #### sub SetStmtCloseType{ my($self, $Type, $Connection) = @_; if (! ref($self)){ $Connection = $Type; $Type = $self; $self = 0; } if (! $Connection){$Connection = $self->{'connection'};} my(@Results) = ODBCSetStmtCloseType($Connection, $Type); return (processError($self, @Results))[0]; } sub ColAttributes{ my($self, $Type, @Field) = @_; my(%Results, @Results, $Results, $Attrib, $Connection, $Temp); if (! ref($self)){ $Type = $Field; $Field = $self; $self = 0; } $Connection = $self->{'connection'}; if (! scalar(@Field)){ @Field = $self->fieldnames;} foreach $Temp (@Field){ @Results = ODBCColAttributes($Connection, $Temp, $Type); ($Attrib) = processError($self, @Results); if (wantarray){ $Results{$Temp} = $Attrib; }else{ $Results .= "$Temp"; } } return wantarray? %Results:$Results; } sub GetInfo{ my($self, $Type) = @_; my($Connection, @Results); if(! ref $self){ $Type = $self; $self = 0; $Connection = 0; }else{ $Connection = $self->{'connection'}; } @Results = ODBCGetInfo($Connection, $Type); return (processError($self, @Results))[0]; } sub GetConnectOption{ my($self, $Type) = @_; my(@Results); if(! ref $self){ $Type = $self; $self = 0; } @Results = ODBCGetConnectOption($self->{'connection'}, $Type); return (processError($self, @Results))[0]; } sub SetConnectOption{ my($self, $Type, $Value) = @_; if(! ref $self){ $Value = $Type; $Type = $self; $self = 0; } my(@Results) = ODBCSetConnectOption($self->{'connection'}, $Type, $Value); return (processError($self, @Results))[0]; } sub Transact{ my($self, $Type) = @_; my(@Results); if(! ref $self){ $Type = $self; $self = 0; } @Results = ODBCTransact($self->{'connection'}, $Type); return (processError($self, @Results))[0]; } sub SetPos{ my($self, @Results) = @_; @Results = ODBCSetPos($self->{'connection'}, @Results); $self->{'Dirty'} = 1; return (processError($self, @Results))[0]; } sub ConfigDSN{ my($self) = shift @_; my($Type, $Connection); if(! ref $self){ $Type = $self; $Connection = 0; $self = 0; }else{ $Type = shift @_; $Connection = $self->{'connection'}; } my($Driver, @Attributes) = @_; @Results = ODBCConfigDSN($Connection, $Type, $Driver, @Attributes); return (processError($self, @Results))[0]; } sub Version{ my($self, @Packages) = @_; my($Temp, @Results); if (! ref($self)){ push(@Packages, $self); } my($ExtName, $ExtVersion) = Info(); if (! scalar(@Packages)){ @Packages = ("ODBC.PM", "ODBC.PLL"); } foreach $Temp (@Packages){ if ($Temp =~ /pll/i){ push(@Results, "ODBC.PM:$Win32::ODBC::Version"); }elsif ($Temp =~ /pm/i){ push(@Results, "ODBC.PLL:$ExtVersion"); } } return @Results; } sub SetStmtOption{ my($self, $Option, $Value) = @_; if(! ref $self){ $Value = $Option; $Option = $self; $self = 0; } my(@Results) = ODBCSetStmtOption($self->{'connection'}, $Option, $Value); return (processError($self, @Results))[0]; } sub GetStmtOption{ my($self, $Type) = @_; if(! ref $self){ $Type = $self; $self = 0; } my(@Results) = ODBCGetStmtOption($self->{'connection'}, $Type); return (processError($self, @Results))[0]; } sub GetFunctions{ my($self, @Results)=@_; @Results = ODBCGetFunctions($self->{'connection'}, @Results); return (processError($self, @Results)); } sub DropCursor{ my($self) = @_; my(@Results) = ODBCDropCursor($self->{'connection'}); return (processError($self, @Results))[0]; } sub SetCursorName{ my($self, $Name) = @_; my(@Results) = ODBCSetCursorName($self->{'connection'}, $Name); return (processError($self, @Results))[0]; } sub GetCursorName{ my($self) = @_; my(@Results) = ODBCGetCursorName($self->{'connection'}); return (processError($self, @Results))[0]; } sub GetSQLState{ my($self) = @_; my(@Results) = ODBCGetSQLState($self->{'connection'}); return (processError($self, @Results))[0]; } # ----------- R e s u l t P r o c e s s i n g F u n c t i o n s ---------- #### # Generic processing of data into associative arrays #### sub updateResults{ my ($self, $Error, @Results) = @_; undef %{$self->{'field'}}; ClearError($self); if ($Error){ SetError($self, $Results[0], $Results[1]); return ($Error); } @{$self->{'fnames'}} = @Results; foreach (0..$#{$self->{'fnames'}}){ s/ +$//; $self->{'field'}->{${$self->{'fnames'}}[$_]} = $_; } return undef; } # ---------------------------------------------------------------------------- # ----------------- D e b u g g i n g F u n c t i o n s -------------------- sub Debug{ my($self, $iDebug, $File) = @_; my(@Results); if (! ref($self)){ if (defined $self){ $File = $iDebug; $iDebug = $self; } $Connection = 0; $self = 0; }else{ $Connection = $self->{'connection'}; } push(@Results, ($Connection, $iDebug)); push(@Results, $File) if ($File ne ""); @Results = ODBCDebug(@Results); return (processError($self, @Results))[0]; } #### # Prints out the current dataset (used mostly for testing) #### sub DumpData { my($self) = @_; my($f, $goo); # Changed by JOC 06-Apr-96 # print "\nDumping Data for connection: $conn->{'connection'}\n"; print "\nDumping Data for connection: $self->{'connection'}\n"; print "Error: \""; print $self->Error(); print "\"\n"; if (! $self->Error()){ foreach $f ($self->FieldNames){ print $f . " "; $goo .= "-" x length($f); $goo .= " "; } print "\n$goo\n"; while ($self->FetchRow()){ foreach $f ($self->FieldNames){ print $self->Data($f) . " "; } print "\n"; } } } sub DumpError{ my($self) = @_; my($ErrNum, $ErrText, $ErrConn); my($Temp); print "\n---------- Error Report: ----------\n"; if (ref $self){ ($ErrNum, $ErrText, $ErrConn) = $self->Error(); ($Temp = $self->GetDSN()) =~ s/.*DSN=(.*?);.*/$1/i; print "Errors for \"$Temp\" on connection " . $self->{'connection'} . ":\n"; }else{ ($ErrNum, $ErrText, $ErrConn) = Error(); print "Errors for the package:\n"; } print "Connection Number: $ErrConn\nError number: $ErrNum\nError message: \"$ErrText\"\n"; print "-----------------------------------\n"; } #### # Submit an SQL statement and print data about it (used mostly for testing) #### sub Run{ my($self, $Sql) = @_; print "\nExcecuting connection $self->{'connection'}\nsql statement: \"$Sql\"\n"; $self->Sql($Sql); print "Error: \""; print $self->error; print "\"\n"; print "--------------------\n\n"; } # ---------------------------------------------------------------------------- # ----------- E r r o r P r o c e s s i n g F u n c t i o n s ------------ #### # Process Errors returned from a call to ODBCxxxx(). # It is assumed that the Win32::ODBC function returned the following structure: # ($ErrorNumber, $ResultsText, ...) # $ErrorNumber....0 = No Error # >0 = Error Number # $ResultsText.....if no error then this is the first Results element. # if error then this is the error text. #### sub processError{ my($self, $Error, @Results) = @_; if ($Error){ SetError($self, $Results[0], $Results[1]); undef @Results; } return @Results; } #### # Return the last recorded error message #### sub error{ return (Error(@_)); } sub Error{ my($self) = @_; if(ref($self)){ if($self->{'ErrNum'}){ my($State) = ODBCGetSQLState($self->{'connection'}); return (wantarray)? ($self->{'ErrNum'}, $self->{'ErrText'}, $self->{'connection'}, $State) :"[$self->{'ErrNum'}] [$self->{'connection'}] [$State] \"$self->{'ErrText'}\""; } }elsif ($ErrNum){ return (wantarray)? ($ErrNum, $ErrText, $ErrConn):"[$ErrNum] [$ErrConn] \"$ErrText\""; } return undef } #### # SetError: # Assume that if $self is not a reference then it is just a placeholder # and should be ignored. #### sub SetError{ my($self, $Num, $Text, $Conn) = @_; if (ref $self){ $self->{'ErrNum'} = $Num; $self->{'ErrText'} = $Text; $Conn = $self->{'connection'} if ! $Conn; } $ErrNum = $Num; $ErrText = $Text; #### # Test Section Begin #### # $! = ($Num, $Text); #### # Test Section End #### $ErrConn = $Conn; } sub ClearError{ my($self, $Num, $Text) = @_; if (ref $self){ undef $self->{'ErrNum'}; undef $self->{'ErrText'}; }else{ undef $ErrConn; undef $ErrNum; undef $ErrText; } ODBCCleanError(); return 1; } sub GetError{ my($self, $Connection) = @_; my(@Results); if (! ref($self)){ $Connection = $self; $self = 0; }else{ if (! defined($Connection)){ $Connection = $self->{'connection'}; } } @Results = ODBCGetError($Connection); return @Results; } # ---------------------------------------------------------------------------- # ------------------ A U T O L O A D F U N C T I O N ----------------------- sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant() # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. my($constname); ($constname = $AUTOLOAD) =~ s/.*:://; #reset $! to zero to reset any current errors. local $! = 0; $val = constant($constname); if ($! != 0) { if ($! =~ /Invalid/) { $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } else { # Added by JOC 06-APR-96 # $pack = 0; $pack = 0; ($pack,$file,$line) = caller; print "Your vendor has not defined Win32::ODBC macro $constname, used in $file at line $line."; } } eval "sub $AUTOLOAD { $val }"; goto &$AUTOLOAD; } # -------------------------------------------------------------- # # # Make sure that we shutdown ODBC and free memory even if we are # using perlis.dll on Win32 platform! END{ # ODBCShutDown() unless $CacheConnection; } bootstrap Win32::ODBC; # Preloaded methods go here. # Autoload methods go after __END__, and are processed by the autosplit program. 1; __END__