NAME
ODBC::Ext.pm - Extentions to the ODBC module
ABSTRACT
This module permits the modification and addition of data in ODBC tables.
It also includes more conginial searching functions.
SECTIONS
ABSTRACT
--
SECTIONS
--
DESCRIPTION
--
BIGER EXAMPLE
--
INSTALLATION
--
AVAILABILITY
--
BUGS!@#!
--
AUTHORS
DESCRIPTION
(more like a history, but what the hey -:)
After looking over the excelent Win32::ODBC module, I realised that it's
oriented towards data retrieval. This, if you ask me, is only half (or
even a third) of what one usualy does with databases. The basic ODBC
functions (in ODBC.pll) didn't include any functions to modify the data
either. I can well understand their lack, I can't make head or tail of
the SqlBind functions either. So I decided to write some wrapers around
the SQL INSERT and UPDATE statements. I also thought it would be useful
to have simpler searching functions and maybe even be able to use Perl
regexs for searching.
Of course, this is only an extention to the old Win32::ODBC package.
All the old functions that we all know and love are still available.
VARIABLES
$newline Static
This variable is appended to each element of an array and each hash key: value
pair when it is used by the
PrepVal
method. It is currently defined as
'%0D%0A'. You could change this to '<p>' if the data is only going to be
used on the web, or anything else that suits your fancy.
METHODS
List
Abort
--
Append
--
DeprepVal
--
Edit
--
FindFirst
--
FindFirstX
--
FindNext
--
Found
--
Get
--
PrepVal
--
Set
--
Table
--
Update
--
new
new ODBC::Ext (['DSNname'])
Creates a ODBC::Ext object and opens a connection to the DSN name given. If
an error occurs (say the DSN doesn't exist), new returns a string that
starts with 'Error: ' followed by an error message.
$odbc = new ODBC::Ext ('Enviro');
if($odbc =~ /^Error:/)
{
die "Connecting to 'Enviro', $odbc";
}
Get ('field')
Returns the value of the given field in the current record. Sql,
FindFirst
,
FindFirstX
or
Edit
should be called first to
select the record.
Note: because I use an SQL statement to modify values, some of them must
be encoded. The Get method therefore decodes everything with
DeprepVal
. See
Edit
for an explanation.
$odbc->Sql("SELECT ID_nom, ID_tele, ID_fax FROM Chercheur"
." WHERE (ID_nom='Jean Drolet'");
print $odbc->Get('ID_nom')."\n";
print $odbc->Get('ID_tele')."\n";
print $odbc->Get('ID_fax')."\n";
Set ('field', $value)
Set the value of the current field to a new value. The changes aren't
writen to disk until the
Update
method is called.
Note: SQL does not permit single quotes (') in a
statement (or if it does, I don't know how). THIS IS VERY ANNOYING! Nor
does it permit exotic characters such as newlines and what not. Ticks
(') are encoded as %27 (ie % followed by the ascii value in hex).
You will need to translate back anything at the other end (
Get
does
this automaticaly).
Another thing to watch out for is date values. Make sure they are in
cannonical form, because 1/3/1995 can be ambiguous.
$personne{'addr'}=['that number','this street','some city'];
$data->Append();
$data->Set('ID_nom', $personne{'nom'});
$data->Set('ID_addr', $data->PrepVal($personne{'addr'}));
$data->Set('ID_tele', $personne{'tele'});
$data->Set('ID_fax', $personne{'fax'});
$data->Set('ID_e_mail', $personne{'e_mail'});
$data->Update();
Edit (['table'])
Prepares the current record for modification. The
Get
and
Set
methods may then be used to modify the record. Changes are only writen
to the table when the
Update
method is called. If the table isn't
specified, the current table is used. Be aware of that
Edit
has some
wonky behaviour. See
BUGS!@#!
.
$odbc->Sql("SELECT * FROM Invoice WHERE ID='00101'")
$odbc->Edit('Invoice');
$odbc->Set('Status', 'done');
$odbc->Update();
Append (['table'])
Creates a new record. The
Set
method should then be used to specify
the data in this record. However, it is only writen to the table when
the
Update
method is called. If the table isn't specified, the
current table is used.
$odbc->Append('Records');
$odbc->Set('Artist', "Engelberg Humperdinkt");
$odbc->Set('Record', "The yodel trance");
$odbc->Update();
Abort ()
Kills the current
Edit
or
Append
. While calling this is STRICTLY
nesecairy, one should to preserve sanity (because you might call
Update
later) and to clean up.
Update ()
Flushes any temporary data to the active table. This adds a record if
Append
was called before, or modifies the record if
Edit
was called.
Be aware of the wonky
Edit
behaviour. See
BUGS!@#!
.
DeprepVal ($scalar)
Converts any escaped values to there original form. ie %27 becomes '.
This function is automaticaly called by the
Get
method, so you
probably don't need it.
PrepVal ($ref)
Prepares a value for use with the
Set
method. Arrays are
joined together, seperated by the
$newline
class variable to form a
string. Hashes under go a similar treatement, except each line is made
up of 'key: value'. Prepval also excapes any caracters that can't be
handled in an SQL statement. Read the perlref man page if you're not an
expert on references.
$hello=$odbc->PrepVal(\@array);
$odbc->Set('Memo_field', $hello);
Table (['table'])
Sets the current table to be used by future calls to
Append
,
Edit
,
FindFirst
and
FindFirstX
. It should NOT be called during an
Append
or
Edit
operation. It can also be used to read the current
table.
print "We are accessing ".$odbc->Table();
FindFirst (['clause'], ['table'])
Find the first record for a given search clause. The current active
table is used if none is given. The search clause is any valid SQL
WHERE clause. I am far from being a SQL expert, so I can't really
enumerate them all here. To find out if a record was found, call
Found
. To proced to the next record in the search, call
FindNext
. If the clause is not given all records will be selected.
This is useful for steping through the entire table.
$odbc->Sql("SELECT * FROM Comp_Books") # see wonky Edit() bug
$odbc->FindFirst('YEAR(start_date) IN (1991, 1992)', 'Comp_Books');
while($odbc->Found())
{
$odbc->Edit();
print $odbc->Set('Obsolete', 'Very!');
$odbc->Update();
$odbc->FindNext();
}
FindFirstX ($sub_clause, ['table'])
This is similar to the
FindFirst
method, except a Perl subroutine is
used to validate each record to see if it should be included in the
search. The subroutine is passed a single parameter: a hash that has all
the field names as keys and their data as values. To find out if a
record was found, call
Found
. To proced to the next record in the
search, call
FindNext
.
I included this mainly so one could do some regex comparisons.
$harold=sub # Note no sub name! Read perlref for an explanation
{ local(%data)=@_;
return ($data{'name'}=~/harold/i);
}
$odbc->FindFirst($harold, 'Kings_of_England');
while($odbc->Found())
{
print $odbc->Get('name')."\n";
print $odbc->Get('death')."\n";
print $odbc->Get('major_wars')."\n";
$odbc->FindNext();
}
FindNext ()
Proceed to the next record in the current search. Searchs are instigated
by
FindFirst
and
FindFirstX
. See those methods for examples.
Found ()
This method revels wether there is currently a record available in the
current search. See
FindFirst
or
FindFirstX
for examples.
BIGER EXAMPLE
require ODBC::Ext;
$odbc= new ODBC::Ext("Monarchs");
$odbc->Append("Kings");
$odbc->Set('name', 'dread fil');
# $odbc->Set('death', 'I'm not dead yet!');
@feats=('Wrote some good CGIs in under 2 hours',
'Learned more than 7 programing languages',
'Played decent guitar',
'Made a profit on self produced educational game',
'Hitch-hiked across Canada (twice)',
'Learned 3 human languages',
'Became frightfuly witty and modest',
);
$odbc->Set('noted_actions', $odbc->PrepVal(\@feats));
$odbc->Update();
$odbc->Append("Queens");
$odbc->Set('name', 'George the Beautious');
$odbc->Set('death', '14/10/1969');
@feets=('Charter member of the Entobicok LASM',
'Never broke a heel',
'Only beat up twice by those THRICE DAMNED gay bashers',
'Learned not to tell construction workers not to F*** off',
'Convinced mother to change nail polish'
'NEVER appeared on Oprah'
);
$odbc->Set('noted_actions', $odbc->PrepVal(\@feets));
$odbc->Abort(); # this example is getting TO SILLY!!!
$odbc->FindFirst('YEAR('death') < 1990');
while($odbc->Found())
{
print 'Here's another moldy one: ', $odbc->Get('name'), "\n";
$odbc->FindNext();
}
# this next example is brought to you by the letters M, L and silent-Q
$sponsor=sub
{ local(%data)=@;
return ($data{'name'}=~/[ML]|(silent-Q)/);
}
$odbc->FindFirstX($sponsor, 'Kings, Queens');
while($odbc->Found())
{
print 'Three cheers for ', $odbc->Get('name'), "\n";
$odbc->FindNext();
}
INSTALLATION
Copy the file Ext.pm to perl-lib-dir\Win32\ODBC\Ext.pm and away you go,
simple as that.
AVAILABILITY
I'll put it at http://www.interlinx.qc.ca/~fil/Perl, for now. Eventualy
I hope to have it in CPAN.
BUGS!@#!
Wonky Edit behaviour.
Ok, there's no hiding it: I'm an SQL neophyte. And I just could get enough
information to understand how to use cursors in SQL. Sigh. This means
the
Update
method uses a WHERE clause to define which record should be
modified. The WHERE clause is defined by all the data in all the fields
currently selected. This could very well be insufficiant to uniquely
select the desired record. So you could very well end up modifing
more than one record.
To work around this bit of sloppy coding, make sure you have enough
fields selected to uniquely define the record. A Sql('SELECT * FROM
George'); usualy does the trick. It should be noted that if your table
has totaly identical records, they will both be modified, no matter
what. But then, databases as a rule shouldn't included such cases.
Of course, you may wish to make use of this feature, but I can't
garanty that it will stick around. -:)
DataHash If you bi-pass Get , values will not be decoded. See Edit .
Other
Other bugs? YES! Probably many. This code might interact in strange
ways with the Win32::ODBC package. Your kilometerage may vary. When in
doubt test test test! and use the source! I knocked this up in an
afternoon (in fact, this documentation is taking longer to write -:) and
don't have the time (nor the inclanation) to extensively debug it. But
then, Perl is a very forgiving language, which is what I ADORE about it.
Long live Larry!
If you find anything out of order, or have comments or sugestions,
please by all means send them to me. But don't expect me to drop
everything to fix a bug.
AUTHORS
Just lil' old me, so far. -:) Philip Gwyn fil@interlinx.qc.ca
DISCLAIMER
This software is provided AS IS, without any warranty, neither explicit
nor implied as to it's suitablilty to any given task. If you crash and
burn because of this software, that's your own look out.