From: Subject: perl.com: A Short Guide to DBI [Oct. 22, 1999] Date: Mon, 18 Feb 2002 12:25:18 +0100 MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_NextPart_000_0000_01C1B877.53988CD0"; type="text/html" X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 This is a multi-part message in MIME format. ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Location: http://www.perl.com/pub/a/1999/10/DBI.html perl.com: A Short Guide to DBI [Oct. 22, = 1999]
3Dwww.perl.com 3D"
3D"O'Reilly3Dperl.com=203DXML.com=203DONLamp.com3DONJava.com3DOpenP2P.com
 O'Reilly's Emerging = Technology=20 Conference: May 13-16, 2002=20
3D"
 
3D"
3D"
  Downloads<= /A>=20
3D"
  
Documentation=20
3D"
  CPAN =
3D"
  FAQs=20
3D"
  Training=20
3D"
  Resources=20
3D"
  Article = Archive=20
3D"
  Books=20
3D"
  Search=20
3D"
  Register/Log = in=20

3D"  Columns
3D" P5P Digest
P6P = Digest
Off the = Wall
Perl=20 Success Stories

3D"

3D"
3D" 3D"O'Reilly

3D"
3D"

 

The Perl = CD=20 Bookshelf, Version 2.0

Advanced = Perl=20 Programming

Beginning Perl for=20 Bioinformatics (October)

CGI = Programming with=20 Perl, 2nd Ed

Developing=20 Bioinformatics Computer Skills

Learning = Perl on=20 Win32 Systems

Learning = Perl, 3rd=20 Edition

Learning=20 Perl/Tk

Mastering = Algorithms=20 with Perl

Mastering = Regular=20 Expressions

mod_perl = Pocket=20 Reference

Perl=20 Cookbook

Perl in a=20 Nutshell

Perl for = System=20 Administration

Perl for = Web Site=20 Management

Perl 5 = Pocket=20 Reference, 3rd Edition

Perl/Tk = Pocket=20 Reference

Programming = Perl, 3rd=20 Edition

Programming = Web=20 Graphics with Perl & GNU Software

Programming = the Perl=20 DBI

Writing = Apache=20 Modules with Perl and C

 

3D"
3D"

3D"
3D"Format

A Short Guide to DBI

by Mark-Jason=20 Dominus
October 22, = 1999=20

Short guide to DBI (The Perl Database Interface Module) =


General information = about=20 relational databases

Relational databases started to get to be a big deal in the = 1970's,=20 andthey're still a big deal today, which is a little peculiar, = because=20 they're a 1960's technology.

A relational database is a bunch of rectangular tables. Each = row of a=20 table is a record about one person or thing; the record contains = several=20 pieces of information called fields. Here is an example = table:=20

 LASTNAME   FIRSTNAME   ID   POSTAL_CODE   AGE  SEX
        Gauss      Karl        119  19107         30   M
        Smith      Mark        3    T2V 3V4       53   M
        Noether    Emmy        118  19107         31   F
        Smith      Jeff        28   K2G 5J9       19   M
        Hamilton   William     247  10139         2    M

The names of the fields are LASTNAME,=20 FIRSTNAME, ID, POSTAL_CODE, = AGE, and SEX. Each line in the table is = a=20 record, or sometimes a row or tuple. = For=20 example, the first row of the table represents a 30-year-old male = whose=20 name is Karl Gauss, who lives at postal code 19107, and whose ID = number is=20 119.

Sometimes this is a very silly way to store information. When = the=20 information naturally has a tabular structure it's fine. When it = doesn't,=20 you have to squeeze it into a table, and some of the techniques = for doing=20 that are more successful than others. Nevertheless, tables are = simple and=20 are easy to understand, and most of the high-performance database = systems=20 you can buy today operate under this 1960's model.

About SQL

SQL stands for Structured Query Language. It was = invented at=20 IBM in the 1970's. It's a language for describing searches and=20 modifications to a relational database.

SQL was a huge success, probably because it's incredibly simple = and=20 anyone can pick it up in ten minutes. As a result, all the = important=20 database systems support it in some fashion or another. This = includes the=20 big players, like Oracle and Sybase, high-quality free or = inexpensive=20 database systems like MySQL, and funny hacks like Perl's=20 DBD::CSV module, which we'll see later.

There are four important things one can do with a table:

SELECT
Find all the records that have a certain property

INSERT
Add new records

DELETE
Remove old records

UPDATE
Modify records that are already there=20

Those are the four most important SQL commands, also called=20 queries. Suppose that the example table above is named=20 people. Here are examples of each of the four = important kinds=20 of queries:=20

 SELECT firstname FROM people WHERE lastname =3D 'Smith'

(Locate the first names of all the Smiths.)=20

 DELETE FROM people WHERE id =3D 3

(Delete Mark Smith from the table)=20

 UPDATE people SET age =3D age+1 WHERE id =3D 247

(William Hamilton just had a birthday.)=20

 INSERT INTO people VALUES ('Euler', 'Leonhard', 248, =
NULL, 58, 'M')

(Add Leonhard Euler to the table.)=20

There are a bunch of other SQL commands for creating and = discarding=20 tables, for granting and revoking access permissions, for = committing and=20 abandoning transactions, and so forth. But these four are the = important=20 ones. Congratulations; you are now a SQL programmer. For the = details, go=20 to any reasonable bookstore and pick up a SQL quick = reference.

Every database system is a little different. You talk to some = databases=20 over the network and make requests of the database engine; other = databases=20 you talk to through files or something else.

Typically when you buy a commercial database, you get a=20 library with it. The vendor has written some functions = for=20 talking to the database in some language like C, compiled the = functions,=20 and the compiled code is the library. You can write a C program = that calls=20 the functions in the library when it wants to talk to the = database.

Every vendor's library is different. The names of the functions = vary,=20 and the order in which you call them varies, and the details of = passing=20 queries to the functions and getting the data back out will vary. = Some=20 libraries, like Oracle's, are very thin=97they just send the query = over to=20 the network to the real database and let the giant expensive real = database=20 engine deal with it directly. Other libraries will do more = predigestion of=20 the query, and more work afterwards to turn the data into a data=20 structure. Some databases will want you to spin around three times = and=20 bark like a chicken; others want you to stand on your head and = drink out=20 of your sneaker.

What DBI is For

There's a saying that any software problem can be solved by = adding a=20 layer of indirection. That's what Perl's DBI = (`Database=20 Interface') module is all about. It was written by Tim Bunce.

DBI is designed to protect you from the details of = the=20 vendor libraries. It has a very simple interface for saying what = SQL=20 queries you want to make, and for getting the results back.=20 DBI doesn't know how to talk to any particular = database, but=20 it does know how to locate and load in DBD (`Database = Driver') modules. The DBD modules have the vendor = libraries=20 in them and know how to talk to the real databases; there is one=20 DBD module for every different database.

When you ask DBI to make a query for you, it sends = the=20 query to the appropriate DBD module, which spins = around three=20 times or drinks out of its sneaker or whatever is necessary to = communicate=20 with the real database. When it gets the results back, it passes = them to=20 DBI. Then DBI gives you the results. = Since your=20 program only has to deal with DBI, and not with the = real=20 database, you don't have to worry about barking like a = chicken.

Here's your program talking to the DBI library. = You are=20 using two databases at once. One is an Oracle database server on = some=20 other machine, and another is a DBD::CSV database = that stores=20 the data in a bunch of plain text files on the local disk.

Your program sends a query to DBI, which forwards = it to=20 the appropriate DBD module; let's say it's=20 DBD::Oracle. DBD::Oracle knows how to = translate=20 what it gets from DBI into the format demanded by the = Oracle=20 library, which is built into it. The library forwards the request = across=20 the network, gets the results back, and returns them to=20 DBD::Oracle. DBD::Oracle returns the = results to=20 DBI as a Perl data structure. Finally, your program = can get=20 the results from DBI.

On the other hand, suppose that your program was querying the = text=20 files. It would prepare the same sort of query in exactly the same = way,=20 and send it to DBI in exactly the same way. = DBI=20 would see that you were trying to talk to the = DBD::CSV=20 database and forward the request to the DBD::CSV = module. The=20 DBD::CSV module has Perl functions in it that tell it = how to=20 parse SQL and how to hunt around in the text files to find the = information=20 you asked for. It then returns the results to DBI as = a Perl=20 data structure. Finally, your program gets the results from=20 DBI in exactly the same way that it would have if you = were=20 talking to Oracle instead.

There are two big wins that result from this organization. = First, you=20 don't have to worry about the details of hunting around in text = files or=20 talking on the network to the Oracle server or dealing with = Oracle's=20 library. You just have to know how to talk to = DBI.

Second, if you build your program to use Oracle, and then the = following=20 week upper management signs a new Strategic Partnership with = Sybase, it's=20 easy to convert your code to use Sybase instead of Oracle. You = change=20 exactly one line in your program, the line that tells = DBI to=20 talk to DBD::Oracle, and have it use = DBD::Sybase=20 instead. Or you might build your program to talk to a cheap, = crappy=20 database like MS Access, and then next year when the application = is doing=20 well and getting more use than you expected, you can upgrade to a = better=20 database next year without changing any of your code.

There are DBD modules for talking to every = important kind=20 of SQL database. DBD::Oracle will talk to Oracle, and = DBD::Sybase will talk to Sybase. = DBD::ODBC will=20 talk to any ODBC database including Microsoft Acesss. (ODBC is a = Microsoft=20 invention that is analogous to DBI itself. There is = no=20 DBD module for talking to Access directly.)=20 DBD::CSV allows SQL queries on plain text files.=20 DBD::mysql talks to the excellent MySQL database from = TCX=20 DataKonsultAB in Sweden. (MySQL is a tremendous bargain: It's=20 $200 for commercial use, and free for noncommerical = use.)

Example of How to Use=20 DBI

Here's a typical program. When you run it, it waits for you to = type a=20 last name. Then it searches the database for people with that last = name=20 and prints out the full name and ID number for each person it = finds. For=20 example:=20

 Enter name> Noether
                118: Emmy Noether

        Enter name> Smith
                3: Mark Smith
                28: Jeff Smith

        Enter name> Snonkopus
                No names matched `Snonkopus'.
       =20
        Enter name> ^D

Here is the code:=20

 use DBI;

        my $dbh =3D DBI->connect('DBI:Oracle:payroll')
                or die "Couldn't connect to database: " . =
DBI->errstr;
        my $sth =3D $dbh->prepare('SELECT * FROM people WHERE =
lastname =3D ?')
                or die "Couldn't prepare statement: " . $dbh->errstr;

        print "Enter name> ";
        while ($lastname =3D <>) {               # Read input from =
the user
          my @data;
          chomp $lastname;
          $sth->execute($lastname)             # Execute the query
            or die "Couldn't execute statement: " . $sth->errstr;

          # Read the matching records and print them out         =20
          while (@data =3D $sth->fetchrow_array()) {
            my $firstname =3D $data[1];
            my $id =3D $data[2];
            print "\t$id: $firstname $lastname\n";
          }

          if ($sth->rows =3D=3D 0) {
            print "No names matched `$lastname'.\n\n";
          }

          $sth->finish;
          print "\n";
          print "Enter name> ";
        }
         =20
        $dbh->disconnect;

 use DBI;

This loads in the DBI module. Notice that we don't = have to=20 load in any DBD module. DBI will do that = for us=20 when it needs to.

 my $dbh =3D DBI->connect('DBI:Oracle:payroll');
                or die "Couldn't connect to database: " . =
DBI->errstr;

The connect call tries to connect to a database. = The first=20 argument, DBI:Oracle:payroll, tells DBI = what=20 kind of database it is connecting to. The Oracle part = tells=20 it to load DBD::Oracle and to use that to communicate = with=20 the database. If we had to switch to Sybase next week, this is the = one=20 line of the program that we would change. We would have to change=20 Oracle to Sybase.

payroll is the name of the database we will be = searching.=20 If we were going to supply a username and password to the = database, we=20 would do it in the connect call:

 my $dbh =3D DBI->connect('DBI:Oracle:payroll', =
'username', 'password')
                or die "Couldn't connect to database: " . =
DBI->errstr;

If DBI connects to the database, it returns a = database=20 handle object, which we store into $dbh. This = object=20 represents the database connection. We can be connected to many = databases=20 at once and have many such database connection obejcts.

If DBI can't connect, it returns an undefined = value. In=20 this case, we use die to abort the program with an = error=20 message. DBI->errstr returns the reason why we = couldn't=20 connect=97``Bad password'' for example.

 my $sth =3D $dbh->prepare('SELECT * FROM people WHERE =
lastname =3D ?')
                or die "Couldn't prepare statement: " . $dbh->errstr;

The prepare call prepares a query to be executed = by the=20 database. The argument is any SQL at all. On high-end databases,=20 prepare will send the SQL to the database server, = which will=20 compile it. If prepare is successful, it returns a=20 statement handle object which represents the statement; = otherwise=20 it returns an undefined value and we abort the program.=20 $dbh->errstr will return the reason for failure, = which=20 might be ``Syntax error in SQL''. It gets this reason from the = actual=20 database, if possible.

The ? in the SQL will be filled in later. Most = databases=20 can handle this. For some databases that don't understand the=20 ?, the DBD module will emulate it for you and will = pretend=20 that the database understands how to fill values in later, even = though it=20 doesn't.

 print "Enter name> ";

Here we just print a prompt for the user.=20

 while ($lastname =3D <>) {               # Read =
input from the user
          ...
        }

This loop will repeat over and over again as long as the user = enters a=20 last name. If they type a blank line, it will exit. The Perl=20 <> symbol means to read from the terminal or = from files=20 named on the command line if there were any.

 my @data;

This declares a variable to hold the data that we will get back = from=20 the database.

 chomp $lastname;

This trims the newline character off the end of the user's = input.

 $sth->execute($lastname)             # Execute the =
query
            or die "Couldn't execute statement: " . $sth->errstr;

execute executes the statement that we prepared = before.=20 The argument $lastname is substituted into the SQL in = place=20 of the ? that we saw earlier. execute = returns a=20 true value if it succeeds and a false value otherwise, so we abort = if for=20 some reason the execution fails.

 while (@data =3D $sth->fetchrow_array()) {
            ...
           }

fetchrow_array returns one of the selected rows = from the=20 database. You get back an array whose elements contain the data = from the=20 selected row. In this case, the array you get back has six = elements. The=20 first element is the person's last name; the second element is the = first=20 name; the third element is the ID, and then the other elements are = the=20 postal code, age, and sex.

Each time we call fetchrow_array, we get back a = different=20 record from the database. When there are no more matching records, = fetchrow_array returns the empty list and the=20 while loop exits.=20

 my $firstname =3D $data[1];
             my $id =3D $data[2];

These lines extract the first name and the ID number from the = record=20 data.=20

 print "\t$id: $firstname $lastname\n";

This prints out the result.

 if ($sth->rows =3D=3D 0) {
            print "No names matched `$lastname'.\n\n";
          }

The rows method returns the number of rows of the = database=20 that were selected. If no rows were selected, then there is nobody = in the=20 database with the last name that the user is looking for. In that = case, we=20 print out a message. We have to do this after the=20 while loop that fetches whatever rows were available, = because=20 with some databases you don't know how many rows there were until = after=20 you've gotten them all.

 $sth->finish;
          print "\n";
          print "Enter name> ";

Once we're done reporting about the result of the query, we = print=20 another prompt so that the user can enter another name.=20 finish tells the database that we have finished = retrieving=20 all the data for this query and allows it to reinitialize the = handle so=20 that we can execute the it again for the next query.=20

 $dbh->disconnect;

When the user has finished querying the database, they type a = blank=20 line and the main while loop exits. = disconnect=20 closes the connection to the database.

Cached Queries

Here's a function which looks up someone in the example table, = given=20 their ID number, and returns their age:

 sub age_by_id {
          # Arguments: database handle, person ID number
          my ($dbh, $id) =3D @_;
          my $sth =3D $dbh->prepare('SELECT age FROM people WHERE id =
=3D ?')
            or die "Couldn't prepare statement: " . $dbh->errstr;

 $sth->execute($id)=20
            or die "Couldn't execute statement: " . $sth->errstr;

 my ($age) =3D $sth->fetchrow_array();
          return $age;
        }

It prepares the query, executes it, and retrieves the result.=20

There's a problem here though. Even though the function works=20 correctly, it's inefficient. Every time it's called, it prepares a = new=20 query. Typically, preparing a query is a relatively expensive = operation.=20 For example, the database engine may parse and understand the SQL = and=20 translate it into an internal format. Since the query is the same = every=20 time, it's wasteful to throw away this work when the function = returns.

Here's one solution:=20

 { my $sth;
          sub age_by_id {
            # Arguments: database handle, person ID number
            my ($dbh, $id) =3D @_;

 if (! defined $sth) {
              $sth =3D $dbh->prepare('SELECT age FROM people WHERE id =
=3D ?')
                or die "Couldn't prepare statement: " . $dbh->errstr;
            }

 $sth->execute($id)=20
              or die "Couldn't execute statement: " . $sth->errstr;

 my ($age) =3D $sth->fetchrow_array();
            return $age;
          }
        }

There are two big changes to this function from the previous = version.=20 First, the $sth variable has moved outside of the = function;=20 this tells Perl that its value should persist even after the = function=20 returns. Next time the function is called, $sth will = have the=20 same value as before.

Second, the prepare code is in a conditional = block. It's=20 only executed if $sth does not yet have a value. The = first=20 time the function is called, the prepare code is = executed and=20 the statement handle is stored into $sth. This value = persists=20 after the function returns, and the next time the function is = called,=20 $sth still contains the statement handle and the=20 prepare code is skipped.

Here's another solution:=20

 sub age_by_id {
          # Arguments: database handle, person ID number
          my ($dbh, $id) =3D @_;
          my $sth =3D $dbh->prepare_cached('SELECT age FROM people =
WHERE id =3D ?')
            or die "Couldn't prepare statement: " . $dbh->errstr;

 $sth->execute($id)=20
            or die "Couldn't execute statement: " . $sth->errstr;

 my ($age) =3D $sth->fetchrow_array();
          return $age;
        }

Here the only change to to replace prepare with=20 prepare_cached. The prepare_cached call = is just=20 like prepare, except that it looks to see if the = query is the=20 same as last time. If so, it gives you the statement handle that = it gave=20 you before.

Transactions

Many databases support transactions. This means that = you can=20 make a whole bunch of queries which would modify the databases, = but none=20 of the changes are actually made. Then at the end you issue the = special=20 SQL query COMMIT, and all the changes are made=20 simultaneously. Alternatively, you can issue the query=20 ROLLBACK, in which case all the queries are thrown = away.

As an example of this, consider a function to add a new = employee to a=20 database. The database has a table called employees = that=20 looks like this:=20

 FIRSTNAME  LASTNAME   DEPARTMENT_ID
        Gauss      Karl       17
        Smith      Mark       19
        Noether    Emmy       17
        Smith      Jeff       666
        Hamilton   William    17

and a table called departments that looks like = this:=20

 ID   NAME               NUM_MEMBERS
        17   Mathematics        3
        666  Legal              1
        19   Grounds Crew       1

The mathematics department is department #17 and has three = members:=20 Karl Gauss, Emmy Noether, and William Hamilton.

Here's our first cut at a function to insert a new employee. It = will=20 return true or false depending on whether or not it was = successful:=20

 sub new_employee {
          # Arguments: database handle; first and last names of new =
employee;
          # department ID number for new employee's work assignment
          my ($dbh, $first, $last, $department) =3D @_;
          my ($insert_handle, $update_handle);

 my $insert_handle =3D=20
            $dbh->prepare_cached('INSERT INTO employees VALUES =
(?,?,?)');=20
          my $update_handle =3D=20
            $dbh->prepare_cached('UPDATE departments=20
                                     SET num_members =3D num_members + 1
                                   WHERE id =3D ?');

 die "Couldn't prepare queries; aborting"
            unless defined $insert_handle && defined =
$update_handle;

 $insert_handle->execute($first, $last, $department) or =
return 0;
          $update_handle->execute($department) or return 0;
          return 1;   # Success
        }

We create two handles, one for an insert query = that will=20 insert the new employee's name and department number into the=20 employees table, and an update query = that will=20 increment the number of members in the new employee's department = in the=20 department table. Then we execute the two queries = with the=20 appropriate arguments.

There's a big problem here: Suppose, for some reason, the = second query=20 fails. Our function returns a failure code, but it's too late, it = has=20 already added the employee to the employees table, = and that=20 means that the count in the departments table is = wrong. The=20 database now has corrupted data in it.

The solution is to make both updates part of the same = transaction. Most=20 databases will do this automatically, but without an explicit = instruction=20 about whether or not to commit the changes, some databases will = commit the=20 changes when we disconnect from the database, and others will roll = them=20 back. We should specify the behavior explicitly.

Typically, no changes will actually be made to the database = until we=20 issue a commit. The version of our program with=20 commit looks like this:=20

 sub new_employee {
          # Arguments: database handle; first and last names of new =
employee;
          # department ID number for new employee's work assignment
          my ($dbh, $first, $last, $department) =3D @_;
          my ($insert_handle, $update_handle);

 my $insert_handle =3D=20
            $dbh->prepare_cached('INSERT INTO employees VALUES =
(?,?,?)');=20
          my $update_handle =3D=20
            $dbh->prepare_cached('UPDATE departments=20
                                     SET num_members =3D num_members + 1
                                   WHERE id =3D ?');

 die "Couldn't prepare queries; aborting"
            unless defined $insert_handle && defined =
$update_handle;

 my $success =3D 1;
          $success &&=3D $insert_handle->execute($first, =
$last, $department);
          $success &&=3D =
$update_handle->execute($department);

 my $result =3D ($success ? $dbh->commit : =
$dbh->rollback);
          unless ($result) {=20
            die "Couldn't finish transaction: " . $dbh->errstr=20
          }
          return $success;
        }

We perform both queries, and record in $success = whether=20 they both succeeded. $success will be true if both = queries=20 succeeded, false otherwise. If the queries succeded, we commit the = transaction; otherwise, we roll it back, cancelling all our = changes.

The problem of concurrent database access is also solved by=20 transactions. Suppose that queries were executed immediately, and = that=20 some other program came along and examined the database after our = insert=20 but before our update. It would see inconsistent data in the = database,=20 even if our update would eventually have succeeded. But with = transactions,=20 all the changes happen simultaneously when we do the = commit,=20 and the changes are committed automatically, which means that any = other=20 program looking at the database either sees all of them or = none.

do

If you're doing an UPDATE, INSERT, or = DELETE there is no data that comes back from the = database, so=20 there is a short cut. You can say=20

 $dbh->do('DELETE FROM people WHERE age > 65');

for example, and DBI will prepare the statement, = execute=20 it, and finish it. do returns a true value if it = succeeded,=20 and a false value if it failed. Actually, if it succeeds it = returns the=20 number of affected rows. In the example it would return the number = of rows=20 that were actually deleted. (DBI plays a magic trick = so that=20 the value it turns is true even when it is 0. This is bizarre, = because 0=20 is usually false in Perl. But it's convenient because you can use = it=20 either as a number or as a true-or-false success code, and it = works both=20 ways.)

AutoCommit

If your transactions are simple, you can save yourself the = trouble of=20 having to issue a lot of commits. When you make the=20 connect call, you can specify an = AutoCommit=20 option which will perform an automatic commit = operation after=20 every successful query. Here's what it looks like:

 my $dbh =3D DBI->connect('DBI:Oracle:payroll',=20
                               {AutoCommit =3D> 1},
                              )
                or die "Couldn't connect to database: " . =
DBI->errstr;

Automatic Error = Handling

When you make the connect call, you can specify a=20 RaiseErrors option that handles errors for you = automatically.=20 When an error occurs, DBI will abort your program = instead of=20 returning a failure code. If all you want is to abort the program = on an=20 error, this can be convenient:

 my $dbh =3D DBI->connect('DBI:Oracle:payroll',=20
                               {RaiseError =3D> 1},
                              )
                or die "Couldn't connect to database: " . =
DBI->errstr;

Don't do This

People are always writing code like this:=20

 while ($lastname =3D <>) {
          my $sth =3D $dbh->prepare("SELECT * FROM people=20
                                   WHERE lastname =3D '$lastname'");
          $sth->execute();
          # and so on ...
        }

Here we interpolated the value of $lastname = directly into=20 the SQL in the prepare call.

This is a bad thing to do for three reasons.

First, prepare calls can take a long time. The = database=20 server has to compile the SQL and figure out how it is going to = run the=20 query. If you have many similar queries, that is a waste of = time.

Second, it will not work if $lastname contains a = name like=20 O'Malley or D'Amico or some other name with an '. The = ' has a special meaning in SQL, and the database will = not=20 understand when you ask it to prepare a statement that looks like=20

 SELECT * FROM people WHERE lastname =3D 'O'Malley'

It will see that you have three 's and complain = that you=20 don't have a fourth matching ' somewhere else.

Finally, if you're going to be constructing your query based on = a user=20 input, as we did in the example program, it's unsafe to simply = interpolate=20 the input directly into the query, because the user can construct = a=20 strange input in an attempt to trick your program into doing = something it=20 didn't expect. For example, suppose the user enters the following = bizarre=20 value for $input:

 x' or lastname =3D =
lastname or lastname =3D 'y

Now our query has become something very surprising:

 =
SELECT * FROM people WHERE lastname =3D 'x'=20
         or lastname =3D lastname or lastname =3D 'y'

The part of this query that our sneaky user is interested in is = the=20 second or clause. This clause selects all the records = for=20 which lastname is equal to lastname; = that is,=20 all of them. We thought that the user was only going to be able to = see a=20 few records at a time, and now they've found a way to get them all = at=20 once. This probably wasn't what we wanted.

References

=95 A complete list of DBD modules are = available here
=95=20 You can download these modules here
=95=20 DBI modules are available here
=95 You=20 can get MySQL from http://www.tcx.se/

People go to all sorts of trouble to get around these problems = with=20 interpolation. They write a function that puts the last name in = quotes and=20 then backslashes any apostrophes that appear in it. Then it breaks = because=20 they forgot to backslash backslashes. Then they make their escape = function=20 better. Then their code is a big message because they are calling = the=20 backslashing function every other line. They put a lot of work = into it the=20 backslashing function, and it was all for nothing, because the = whole=20 problem is solved by just putting a ? into the query, = like=20 this=20

 SELECT * FROM people WHERE lastname =3D ?

All my examples look like this. It is safer and more convenient = and more efficient to do it this way.

3D"


3D"
3D" 3D"=20
<= /TBODY>
3D"About
3D"
Compilation Copyright =A9 1998-2002 O'Reilly & = Associates,=20 Inc. All Rights Reserved.
All trademarks and registered = trademarks=20 appearing on perl.com are the property of their respective = owners.
For=20 problems or assistance with this site, email help@www.perl.com
------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/jpeg Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/75-logo.jpg /9j/4AAQSkZJRgABAgEASABIAAD/7QIoUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAA0cAgAAAgAC HAJ4AAEAADhCSU0D6QAAAAAAeAAoAAAASABIAAAAAALnAlL/9//3Aw8CWyACBSgD/AAAAAAC0ALQ AAAAAB0GFzQC6AAyFzSRUACVAAEBAQAAAAEnDwABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAGQD AAAAAAAAAAAAMLAEQCEABAAAAAAANUxhIDhCSU0D7QAAAAAAEABIAAAAAQABAEgAAAABAAE4QklN BA0AAAAAAAQAAAB4OEJJTQPzAAAAAAAIAAAAAAAAAAA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAA CgABAAAAAAAAAAI4QklNA/UAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAA AAEAMgAAAAEAWgAAAAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA/gAAAAAAHAAAP////// //////////////////////8D6AAAAAD/////////////////////////////A+gAAAAA//////// /////////////////////wPoAAAAAP////////////////////////////8D6AAAOEJJTQQIAAAA AAAVAAAAAQAAAkAAAAJAAAAAAQAAGwABADhCSU0EFAAAAAAABAAAAAM4QklNBAYAAAAAAAcACAAA AAEBAP/uAA5BZG9iZQBkQAAAAAH/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQECAgICAgICAgICAgMDAwMDAwMDAwMBAQEBAQEBAQEBAQICAQICAwMDAwMDAwMD AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA//AABEIAEsAzQMBEQACEQED EQH/3QAEABr/xAGiAAAABgIDAQAAAAAAAAAAAAAHCAYFBAkDCgIBAAsBAAAGAwEBAQAAAAAAAAAA AAYFBAMHAggBCQAKCxAAAgEDBAEDAwIDAwMCBgl1AQIDBBEFEgYhBxMiAAgxFEEyIxUJUUIWYSQz F1JxgRhikSVDobHwJjRyChnB0TUn4VM2gvGSokRUc0VGN0djKFVWVxqywtLi8mSDdJOEZaOzw9Pj KThm83UqOTpISUpYWVpnaGlqdnd4eXqFhoeIiYqUlZaXmJmapKWmp6ipqrS1tre4ubrExcbHyMnK 1NXW19jZ2uTl5ufo6er09fb3+Pn6EQACAQMCBAQDBQQEBAYGBW0BAgMRBCESBTEGACITQVEHMmEU cQhCgSORFVKhYhYzCbEkwdFDcvAX4YI0JZJTGGNE8aKyJjUZVDZFZCcKc4OTRnTC0uLyVWV1VjeE haOzw9Pj8ykalKS0xNTk9JWltcXV5fUoR1dmOHaGlqa2xtbm9md3h5ent8fX5/dIWGh4iJiouMjY 6Pg5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6vr/2gAMAwEAAhEDEQA/AN/dmVFLMQqqCWYkAKAL kkngAD37r3RUNufO/wCE+7+0T0ltT5bfHDcfb38Smwy9a4Tubr7J71lzFO5jnxEG3qPcEuSqMpDI CrU6RtMGBGm4I9+690I2/fkd8f8Aqxd4v2X3b1VsBevKLbmR3428d+bZ26NmY/eFX9jtWt3R/Fcl S/wOl3JW/tUL1PjWqk9MZY+1DWd3HawXslrItlIxVHKkIzL8QVqUJHmAcdJY720lup7GO5ja9iUM 6BgXVW+EsvEA+RIz1G2l8nPjjv8A6y3B3RsbvnqDePUO04cnPuns7bHY20s7sTbcOGg+5y0me3Vj MtU4XEJjaYiSf7iaPxxkM1gQfafpV0G+1/n98G97w7pqdnfMD41bqp9j7cm3hvKbb3dXXmYi2rtS nr6LFz7k3C9Bn51xGEhyWSp6dqmfRCs08aFtTqD7r3RhNp9k9e79r91YrZG99q7uyexcvS4DelBt zPYzM1m1M3W4qiztHiNw09BUzy4jI1WFyFPVxwziOR6eZJACrAn3XukBm/k/8c9t7E3V2hnu9OqM T1vsXedR11vbfldvvbkG0dob8pMxSbfq9n7n3C2QGLwO4aPO10NHNS1UsU0VTKkbqGYA+690qt89 zdS9ZPsSPsPsrZGy5e0d1YzY/W0O5dzYjETb93jmoJKnFbZ2fDWVUUu4s1X0sLyx09IJZGiQvbSC ffuvdd9Y9y9Td1YvL5vqLsnZPZmHwGdrtsZrKbG3LidzUGL3DjGVa/D1tViaqqhgrqUsNSMQbG44 9+690Jfv3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917pDd 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 ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/trans.gif R0lGODlhAQABAOYAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yH5 BAEAAH8ALAAAAAABAAEAAAcDgH+BADs= ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/tabs/tab-grey-oreilly.gif R0lGODlhXgASAMQAAP////v7+/Ly8uvr697e3tzc3NfX19PT083NzczMzL+/v7KysqamppaWloiI iHt7e25ubl5eXlJSUjc3NycnJxoaGg4ODgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA XgASAAAF/yAgAsFAHEmqrmzrvnAsy8hBDMGoC8Xs/8DgryDQAQQGoXLJnBmKokCvSa02CznAwMrt AgcigndMbhFEqLJ6fBAhlo+KJZK62OkQ+wWST/RTExMJC3uEECkKEhcVDAkRFhUPCQ17CQoVgkoi S4QSeZJ7DhcMf34XpiqBKRJzFgopEBYPDgwPe4oLlK55mUKbSravFBIJe7YLpX2lqoN3KsMqEhSW Fw+6jxa9Qb9Cf6p6h3l2DcqngL24KpXndRCUvMy+AHAXwsR7E8TJp8u9pQnQVk1TUI1SgwkHtQHh FoRQBFGgIATbZ6pBgwUTKFhU0EeBAz8WHDyoVS1PrgsXEzbE2zYPjhw6xSAYErennB0IE/SQO+Vg oKIKCxxBkmSQnaaWa5JyYai06RKmTqP+gCq1KgwAIQAAOw== ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/tabs/tab-grey-on.gif R0lGODlhXAASANUAAP///xgYGDk5OVJSUnt7e5SUlLW1tc7Ozvf3986lpc4AnM4InM4hnM5anM6E nAAAAPv7+/Ly8uvr697e3tzc3NfX19PT083NzczMzL+/v7KysqamppaWloiIiG5ubl5eXkRERDc3 NycnJxoaGg4ODgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAXAASAAAG/0CAECKZWDDIpHLJ bDqf0Gj0YplIIMJshCLter9gLyWirYTP6LS0QoZw1fC4mkKU2+/fIn7PZxr7gHwWF0sEIyQfGBok HR4PDyMbGCGPDxwhIZOZSA8eGASWoBxJHA8EGJ2ljyGOlR8kGB0PHRiIGSAPIpKUDyEZjhgeJBlQ Gg8DjgQZIx7AIiCaSZjRnJ4YI5ibSKUjqB6lo0mdGKUbHw8fG5YDjCLdmBmdjhkk1k+gxCIDGfvA IwPUok2rhgTULCWqQH2zpGRcLQ+HmMEakUiWBkzGCDgSRgwKsICtRmiYVEmgNofXuiHsRWnhI2sO B4wwBQngOHC8MjkiAS0KPoMM+pI4KjVyoElx9oxum0UiFUOkSGR1m0mLYqwHF1l12/hAUjF0sk4h 8ZfI6LQQIjhwiDdAbcClHM4tDEcQQ7xE54ix4wDiXQhjjR4s03bvUCKhDzDIzMDL0tlKqh69JWfJ mMtedTGAoMUXya1cuzKNAAFMlr1AqFOrXs26tevXsJcEAQA7 ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/tabs/tab-perlblk.gif R0lGODlhYAASANUAAP///xgYGDk5OVJSUnt7e5SUlLW1tc7Ozvf3986lpc4AnM4InM4hnM5anM6E nAAAAO7u7urq6t7e3ry8vLq6uqqqqpycnJmZmYmJiXV1dWVlZVhYWFVVVU9PT0RERDY2NjAwMCMj IyAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAYAASAAAG9ECAMGLZhB7IpHLJ bDqf0KhUGdpYIsLspDPter/gaWei/YTP6LT0Q45w1fC4ukOU2+/fIn7PbxrlHkISHg8UWR6GABQj gYRKIxcAEiAPGBASGg+BGQ8jEhR3R4AAHhcShaBIFIsAGY1LGRAaHCAarZEigRAjGYp9cI29qEmr IgAar0oHF0kXB53HupYQqb9ogQcQGIVZ3L7JSa3Eqa2biqvWaZuUw6oUGafgSMvNzyPRpBSI1elg 4OjujHHY5AGEwQexOGiodaxXLlIi2vXzR4rYIXQSKgQSQgHDNkiSIlrCpKmixIkoU6pcybKly5cw Y8psEgQAOw== ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/tabs/tab-xml.gif R0lGODlhXgASAMQAAP////v7+/Ly8uvr697e3tzc3NfX19PT083NzczMzL+/v7KysqamppaWloiI iHt7e25ubl5eXlJSUkRERDc3NycnJxoaGg4ODgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA XgASAAAF/yAgAsFAHEmqrmzrvnAsy8hBDMGoC8Xs/8DgryDQAQQGoXLJnBmKokCvSa02CznAwMrt AgcigndMbhFEqLJ6fBAhug3MY4GBxCEJhYWSqLcgFxcPCQ8WFxEpGBMpExhdImMUFhIXCnGVEBh8 fit3DQ50EpmDGBgNcY5ckF4MpXiXEYGbeCsRFioPGAoJFRJ9FxQUF6lWq14WGAsJd5rBfbQqzimZ Kc4YsYfEVcZcuRe+cQ0U4rMstri6vL51EO3aVNxVehSZDOHK1hKnCg7LdQ6grjmQ80yBAmqqAHjJ 1EABsHDVNpXC4KDCtED9Ch1KRAthMYVrQj4CKbJkk3gmUwn+QKmyJQwAIQAAOw== ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/tabs/tab-grey-onlamp.gif R0lGODlhXAASANUAAP///xgYGDk5OVJSUnt7e5SUlLW1tc7Ozvf3986lpc4AnM4InM4hnM5anM6E nAAAAPv7+/Ly8uvr697e3tzc3NfX19PT083NzczMzL+/v7KysqamppaWloiIiG5ubl5eXkRERDc3 NycnJxoaGg4ODgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAXAASAAAG/0CAECKZWDDIpHLJ bDqf0Gj0YplIIMJshCLter9gLyWirYTP6LS0QoZw1fC4mkKU2+/fIn7PZxr7gHwWF2EEIyQfSA8D GCEhGA8eSR0PiY0jGRgeDxybDyEaSBshDyIYGSClG5oPqxuRgUsai5sEkA8ajpCSSB+lSKQeGSSc mxgjjI0iHZIDJB0iI6yPwbFKBA+ZIowPi7qwSCKkmSEkiMSdD42PGQ+2SCOJlBqbJB7EvNaswI+f JOK7kLTj8KDDumDFPhXEQJBDElgNN0kEpw+bNm4eSPXjRekDonUcQkTkFOqUuyTxMMzblAETRWuz PlCyFYlSvwEcOHwYkdGULjsNI5F0ICeiEwZnHEBIMxbqpTVDHwOO6NftATIM2HI9YpgwnMFRn06l ErHKmKJ8+tKqXcu2rdu3cK0FAQA7 ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/tabs/tab-grey-onjava.gif R0lGODlhXgASANUAAP///xgYGDk5OVJSUnt7e5SUlLW1tc7Ozvf3986lpc4AnM4InM4hnM5anM6E nAAAAPv7+/Ly8uvr697e3tzc3NfX19PT083NzczMzL+/v7KysqamppaWloiIiG5ubl5eXkRERDc3 NycnJxoaGg4ODgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAXgASAAAG/0CAEACRTCyYpHLJ bDqf0KhUerFMJJChNkKZer/g8JcS0QIiFbF6zZ5WykJIt02vtylZgMTO74MlQhN+g4RNE0JIhYqD FkIXbAQjJB9JDwMYISEYDx4YHQ+UIpoeDxkfDx1MHiQkBBiRk5UgSSAPbUJsGpakrg8PGpmbnaci GKQZIcUioEscnBwdugO8mw8czrZsuGsEpRgil74DwZzfIaW63R4ZD8lLHyNK3Rnf4SSZJNlr22qk SeQhSIgSxs5ZKhEjfn1yRu+fpiT+MGkCxerULQCQvIETdm6ih08fYpEqFvJUqiTw5GkM56FlxH0Y 1+j68KnXx3bC4Hlwt6GcKEkPIz5kSOXsYzRQNQlmeKmGnxpYlIRhGOFxxKVuGqZuSIdhwIgOxYyx SgW1Uidj+prGLFR0ER+ngyRldVsHrp+tdO3YzcsXDIAgADs= ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/tabs/tab-grey-p2p.gif R0lGODlhXAASANUAAP///xgYGDk5OVJSUnt7e5SUlLW1tc7Ozvf3986lpc4AnM4InM4hnM5anM6E nAAAAPv7+/Ly8uvr697e3tzc3NfX19PT083NzczMzL+/v7KysqamppaWloiIiG5ubl5eXkRERDc3 NycnJxoaGg4ODgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAXAASAAAG/0CAECKZWDDIpHLJ bDqf0Gj0YplIIMJshCLter9gLyWirYTP6LS0QoZw1fC4mkKU2+/fIn7PZxr7gHwWF2EEIyQfSA8P JB4YIYsPHB4PGhySlA8hGhoiDyAZj4sDSR0jD4kbnqCPI6GUHIEYGg8DlAQYDx4ElSEhSZQDl5MP GCMDGwS3j5sPuBkkIBy4IyIdJKSQHtCSsryhIqS6w77Ai7zEzEm66uwdlUi0HRgfI48kiCTdgZRI 5Q8jqolahIGSL0yaHszD8O2eCBIaChZDMkwiM237ADUMl0uYv19IYC0ixiEihgwjEj0SwSEUhncm 5dGz54tDiIqBaH14h4vdRzxzGDylS/KBRIdY5RiexDbJ2M1j6ixl1HhIpc+BCBlmRfIuUtQREU2x U/UpVFKcstKqXcu2rdu3cOM2CQIAOw== ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/pixel-perl.gif R0lGODlhAQABAMQAAP///xgYGDk5OVJSUnt7e5SUlLW1tc7Ozvf3986lpc4AnM4InM4hnM5anM6E nAAAAABmmQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA AQABAAAFAyAUAgA7 ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/perl-arrow-on-bg.gif R0lGODlhCgAMAMQAAP///xgYGDk5OVJSUnt7e5SUlLW1tc7Ozvf3986lpc4AnM4InM4hnM5anM6E nAAAAABmmQBgjwBZhgBTfABLcABEZgA3UwAvRwAiMwANFAA+XAApPQAcKQAUHQAHCgAAACwAAAAA CgAMAAAFLSAFjST5bFJpPp6lQk/8ZFUpy9w03vcW8TcL8IFJ8TqiXcyjUcUukRcn9YKEAAA7 ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/jpeg Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/books/perlbooks.jpg /9j/4AAQSkZJRgABAgEASABIAAD/7gAOQWRvYmUAZEAAAAAB/9sAhAABAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAgICAgICAgICAgIDAwMDAwMDAwMDAQEBAQEBAQEB AQECAgECAgMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwP/ wAARCAAoAH0DAREAAhEBAxEB/90ABAAQ/8QBogAAAAYCAwEAAAAAAAAAAAAABwgGBQQJAwoCAQAL AQAABgMBAQEAAAAAAAAAAAAGBQQDBwIIAQkACgsQAAIBAwQBAwMCAwMDAgYJdQECAwQRBRIGIQcT IgAIMRRBMiMVCVFCFmEkMxdScYEYYpElQ6Gx8CY0cgoZwdE1J+FTNoLxkqJEVHNFRjdHYyhVVlca ssLS4vJkg3SThGWjs8PT4yk4ZvN1Kjk6SElKWFlaZ2hpanZ3eHl6hYaHiImKlJWWl5iZmqSlpqeo qaq0tba3uLm6xMXGx8jJytTV1tfY2drk5ebn6Onq9PX29/j5+hEAAgEDAgQEAwUEBAQGBgVtAQID EQQhEgUxBgAiE0FRBzJhFHEIQoEjkRVSoWIWMwmxJMHRQ3LwF+GCNCWSUxhjRPGisiY1GVQ2RWQn CnODk0Z0wtLi8lVldVY3hIWjs8PT4/MpGpSktMTU5PSVpbXF1eX1KEdXZjh2hpamtsbW5vZnd4eX p7fH1+f3SFhoeIiYqLjI2Oj4OUlZaXmJmam5ydnp+So6SlpqeoqaqrrK2ur6/9oADAMBAAIRAxEA PwDX56I+LfbHffY/bcvxO7Rqt5ZrZdPtfO9nb8ymFzlEOvcznqyCp3zQ0GYyeHxOJ3fjMbXCOmhg WnbNTiklnih8LSiX3Xur0/hP/Mg+Rn8rvv3L9Z/KLDf6WfjhvCXMRVu5+u91YeulO5aKTG02W3R1 3iqugxUm9clhtzwV9FkZ8jV0rZBY6gKaYwQBvde62regf5n/AMM/kvgsDuLq3sfc1Rjtw0UdXTNu Dqvs7AijlYUjTYzI1021Z8KmTo48hTvMsFXPCqVEbLKwa/v3XuhF3J89PiRsiuyWO3/3Pj+uqvFI s1SvYe0extjwS0Lg6ctj67c+zsZj8nhTKDF97Tyy0oqAYTIJQUHuvdGF677J2D25s/E9gdX7025v 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 ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/print.gif R0lGODlhZgAWAPcAAP///xgYGDk5OVJSUnt7e5SUlLW1tc7Ozvf3986lpc4AnM4InM4hnM5anM6E nAAAAP7+/v39/fz8/Pv7+/r6+vn5+fj4+Pb29vX19fT09PPz8/Hx8fDw8O/v7+3t7ezs7Ovr6+rq 6unp6efn5+bm5uXl5eTk5OPj4+Li4uHh4eDg4N/f397e3t3d3dzc3Nvb29ra2tnZ2djY2NfX19bW 1tXV1dHR0c/Pz8XFxcPDw8HBwb+/v76+vr29vbu7u7m5ubS0tLOzs7KysrCwsK+vr6ysrKurq6qq qqSkpKGhoZ+fn56enpqampmZmZeXl5aWlouLi4qKioiIiISEhH9/f319fXx8fHp6enl5eXd3d3Z2 dnV1dXR0dHNzc3JycnFxcW5ubmpqamZmZmNjY2JiYmBgYF5eXl1dXVxcXFtbW1lZWVhYWFdXV1ZW VlVVVVNTU1FRUVBQUE9PT01NTUxMTEpKSklJSUhISEdHR0ZGRkVFRURERD8/Pz4+PjY2NjQ0NDIy MjExMSsrKyoqKiIiIiEhIR8fHx4eHh0dHRwcHBoaGhYWFhUVFRQUFBEREQ4ODgwMDAoKCgkJCQgI CAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAZgAWAAAI/wABAIgQ oQIEgQgTIpQAIYLChxAjSpxIsaJFgRQOCtThREkTJ06ePGmSpAeACRdTqlzJUmEECQIRwZHSxUsW LlimoEkk0GHLn0CDAtC4IQ4JiAgACV3K9CIEmALdyICIwY9AjU2zau0JIIOAEgixcrAjEOXWs0J9 AlgzqULChgAQRLKBti5TLX66aLiqFsAiARnsCv55Zg4BiX32hB3MmGIJK4QeHArDRg4TI2D41OHy YNIYIo1DR0SgpsiFCBhM3CBBR1KPEjJMZNAQ4o4PhSuiRGGC+/bE3Lqj5E7IOyKT4sYVMvFdMcIA HBZEoPBwQwOOJRZSiBgBggWENT8U+v94EMVRFOJiHnZAnruQnijjExZaEfHBA/W8VxRS+D7lHi1T bHGFFlgQAEUVVlyxRRYKIjFIDuLdF4Ueud2wHG9R3JBhB4HogRwA/Y2nYQcACJfbh0c44sgRJWqo QodMDAeAD8L1lxt9ElVQBgYWWQBAFUBEqMcDR4wXiBgTAvBAIG44wqEYNyQU4gNuMKmkDyueh5AW erihhZKFBPLkDfExYd4R/RVi5kQVsNHCBzHMAEMML7jwQgwyxEADngCAMUSEPtA3HotJPuBDfP1J eV58hfrQpJYCdahHIEp+CeKi9yX63nhDMvfQBWyYEIIKJZRqAgommJCCCSCQQAMAYQjEESFC8ZWo x5WIakEiQlPaiut4vnXwgBhiPCCsb3roGp8Yt3bw3goP3LBrRBOs4UFKWxgxq0C1NlrmsIrOKOGt hg55q0BHGCtsur4xMWx8KwzJRH9aLEnRGnUQkIckjzQSgCIBMCIwJIdo8UUiMIimcEI/vNEBDneQ 0YYfhBAiSB1jyEEFAE2QsfDHACDxRQdE+KBDDzWMcMIJO/DQQxAz6PAGyAtXwMUa9j0QCR5pwGGG IQ9Q8sAfZrhA88dmUQTV0YMFBAA7 ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com//1999/10/dbi.gif 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 qQxv4U1Z3mn9QwEAADs= ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/trail-about.gif R0lGODlhMgAQAMQAAP///xgYGDk5OVJSUnt7e5SUlLW1tc7Ozvf3986lpc4AnM4InM4hnM5anM6E nAAAAO/v79/f38/Pz7u7u6qqqpqamoqKinZ2dmZmZlVVVUVFRTExMSEhIREREQAAAAAAACwAAAAA MgAQAAAFviAgjmRpnmiqrmzrvnAsz+MEtVYlTlZ+ixSLZGcRWSa83tH0mLAmj4fxoel0bpjoo2iR AraVakejKzVZF86DAugCKA+JZAvIdNpeOkCjQZ1XG3YXeBYbG3g7TW5fRXt9J38pEFsZh10aHB0R i1A8eY18fk4qcBtqEG6TFnARABUPm58ioZCjKRdbWUGKDxUQHRsWYwBzGRl/tEy2KByHXxhdDxyD xBsPGa1tHByNjqI04LXh4yOR5OAaQ+frIyEAOw== ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/trail-contact.gif R0lGODlhTAAQALMAAP///+/v79/f38/Pz7u7u6qqqpqamoqKinZ2dmZmZlVVVUVFRTExMSEhIRER EQAAACwAAAAATAAQAAAE/xDISau9OOvNu/9gKI5kaZ6kMHjFsQKBcQiSLB0Ecew4YE+tFW9HEcx8 htqxclh0Eo8ojBF1EACLx/VxMCwcjkUyegVApQsqwzkhaLHO74JNaXIEjwSAdngMAg0KWA9OXBJz EgUPDQh7eXsSbmVtb4iPARZ2GwYPmIdsfVgOD4oHnxIIDgoMPp0UkhWwiAgPSZl0GaETiAChcwsN hnASDAp9AbqUk5GVbFC2dbgYii8ACA0SCdhzbsKIAYtUBdSvb+VX3wAKDrccAQ4Ndm4KtKaIUKbD igl9CO/xbGBVcMCgHoB4DLAxkYZhABU9Pho48DcMT757roABcPgIgEAKBR4YOEiAKQHBZTcYolg5 QhPLly1VwpypwUAjmjhJRAAAOw== ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.perl.com/images/trail-privacy.gif R0lGODlhXgAQALMAAP///+/v79/f38/Pz7u7u6qqqpqamoqKinZ2dmZmZlVVVUVFRTExMSEhIRER EQAAACwAAAAAXgAQAAAE/xDISau9OOvNu/9gKI5kaZ5oqopEsAnHYQgAHNOwUBySwcOECcwQIBwG ABnFeCi4AAEfDWAwTIyTHTIGME4pj6CG8GA0HAKy+ZEOGx7OhyL5WEgGjsfjEHAoCg9WEwd1DgxQ DHoOQQt2EoQSCXoPdANmF2EbZC17mwCdYQEPCYBWay4JDkg0hAsOFZCARg8DAQ1zjYOUAqM1UA4L e5hiGWQxgWQJCmGeCg2SAaKSBQANCBR9whSEBJICuXQA4OFvT48PDuZgxBhkegldDw29nm9+AIB4 19oTCA/qdNDxAAdpHCRI2B5cG6Ypk4RNiYpkEhUIgD9XhxjM2UYJVkcJCGoaRBJpkFK+CvxQsrvg 6WEYQgVaLnNh5kCwAIQSIOARzuMSOf4GMiBAAAalPg1sTki5riGxTQMUtjQwh9c1MlYQOGggBiHH CgbOIHARTM+xO4ngSWC6dOWKt3Dbxp071yHduykWIMHLF24EADs= ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: text/css; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Location: http://www.perl.com/styles/linux-px.css .tiny { FONT-SIZE: 11px; FONT-FAMILY: helvetica, sans-serif } .tinywhite { FONT-SIZE: 11px; COLOR: #ffffff; FONT-FAMILY: helvetica, sans-serif } .secondary { FONT-SIZE: 13px; FONT-FAMILY: helvetica, sans-serif } .intro { FONT-SIZE: 13px; FONT-FAMILY: helvetica, sans-serif } .headline { FONT-WEIGHT: bold; FONT-SIZE: 13px; FONT-FAMILY: helvetica, sans-serif } .techlink { FONT-WEIGHT: bold; FONT-SIZE: 11px; FONT-FAMILY: helvetica, sans-serif; = TEXT-DECORATION: none } .header { FONT-WEIGHT: bold; FONT-SIZE: 13px; COLOR: #ffffff; FONT-FAMILY: = helvetica, sans-serif } .title { FONT-WEIGHT: bold; FONT-SIZE: 15px; FONT-FAMILY: helvetica, sans-serif } .titlewhite { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #ffffff; FONT-FAMILY: = helvetica, sans-serif } .smalltext { FONT-SIZE: 11px; FONT-FAMILY: helvetica, sans-serif } .smalllist { MARGIN-TOP: 6px; FONT-SIZE: 11px; MARGIN-BOTTOM: 6px; FONT-FAMILY: = helvetica, sans-serif } .medlist { MARGIN-TOP: 6px; FONT-SIZE: 13px; MARGIN-BOTTOM: 6px; FONT-FAMILY: = helvetica, sans-serif } .zeromarg { MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px } .noline { COLOR: #ffffff; TEXT-DECORATION: none } .nolineblack { FONT-WEIGHT: bold; FONT-SIZE: 11px; COLOR: #000000; FONT-FAMILY: = helvetica, sans-serif; TEXT-DECORATION: none } .message { FONT-SIZE: 13px; FONT-FAMILY: helvetica, sans-serif } .pullnet { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #990000; FONT-FAMILY: 'Times = New Roman',Times,serif } .pulllinux { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #660000; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullapache { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #006666; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullpatents { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #666699; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullrss { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #006600; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullbsd { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #663366; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullwireless { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #6699cc; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullpython { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #990066; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullmac { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #660099; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullmozilla { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #669900; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullphp { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #009999; FONT-FAMILY: 'Times = New Roman',Times,serif } .pullp2p { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #993399; FONT-FAMILY: 'Times = New Roman',Times,serif } .pulljava { FONT-WEIGHT: bold; FONT-SIZE: 15px; COLOR: #cc0033; FONT-FAMILY: 'Times = New Roman',Times,serif } .network { COLOR: #990000 } .linux { COLOR: #660000 } .apache { COLOR: #006666 } .patents { COLOR: #666699 } .rss { COLOR: #006600 } .bsd { COLOR: #663366 } .wireless { COLOR: #6699cc } .python { COLOR: #990066 } .mac { COLOR: #660099 } .mozilla { COLOR: #669900 } .p2p { COLOR: #993399 } .php { COLOR: #009999 } .mysql { COLOR: #cc00cc } .perl { COLOR: #006699 } .red { COLOR: #990000 } .servlets { COLOR: #cc0033 } .xml { COLOR: #009900 } FORM { MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px } INPUT { MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px } H1 { FONT-SIZE: 19px; FONT-FAMILY: helvetica, sans-serif } H2 { FONT-SIZE: 19px; FONT-FAMILY: helvetica, sans-serif } H3 { FONT-WEIGHT: bold; FONT-SIZE: 15px; FONT-FAMILY: helvetica, sans-serif } H4 { PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: = bold; FONT-SIZE: 13px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 0px; = PADDING-TOP: 0px; FONT-FAMILY: helvetica, sans-serif } CODE { COLOR: #003366; FONT-FAMILY: Courier,monospace } ------=_NextPart_000_0000_01C1B877.53988CD0 Content-Type: application/octet-stream Content-Transfer-Encoding: quoted-printable Content-Location: http://www.perl.com/common.js // common js code for network=0A= //Clear inherited frames=0A= =0A= if (parent !=3D self) {=0A= top.location=3Dself.document.location;=0A= }=0A= =0A= //random number for dc=0A= //var ord =3D Math.round(Math.random() * 10000000000);=0A= var abc =3D Math.random() + "";=0A= var ord =3D abc.substring(2,abc.length);=0A= =0A= //detect browser-os and choose style sheet=0A= =0A= =0A= ------=_NextPart_000_0000_01C1B877.53988CD0--