File Coverage

blib/lib/Dancer/Plugin/Database/Core/Handle.pm
Criterion Covered Total %
statement 80 156 51.2
branch 37 98 37.7
condition 19 51 37.2
subroutine 8 16 50.0
pod 6 7 85.7
total 150 328 45.7


line stmt bran cond sub pod time code
1             package Dancer::Plugin::Database::Core::Handle;
2              
3 2     2   28535 use strict;
  2         2  
  2         44  
4 2     2   6 use Carp;
  2         2  
  2         109  
5 2     2   1380 use DBI;
  2         11579  
  2         70  
6 2     2   9 use base qw(DBI::db);
  2         2  
  2         3562  
7              
8             our $VERSION = '0.15';
9              
10             =head1 NAME
11              
12             Dancer::Plugin::Database::Core::Handle - subclassed DBI connection handle
13              
14             =head1 DESCRIPTION
15              
16             Subclassed DBI connection handle with added convenience features
17              
18              
19             =head1 SYNOPSIS
20              
21             # in your Dancer app:
22             database->quick_insert($tablename, \%data);
23              
24             # Updating a record where id = 42:
25             database->quick_update($tablename, { id => 42 }, { foo => 'New value' });
26              
27             # Fetching a single row quickly in scalar context
28             my $employee = database->quick_select('employees', { id => $emp_id });
29              
30             # Fetching multiple rows in list context - passing an empty hashref to signify
31             # no where clause (i.e. return all rows - so "select * from $table_name"):
32             my @all_employees = database->quick_select('employees', {});
33              
34             # count number of male employees
35             my $count = database->quick_count('employees', { gender => 'male' });
36              
37             =head1 Added features
38              
39             A C object is a subclassed L L
40             database handle, with the following added convenience methods:
41              
42             =over 4
43              
44             =item quick_insert
45              
46             database->quick_insert('mytable', { foo => 'Bar', baz => 5 });
47              
48             Given a table name and a hashref of data (where keys are column names, and the
49             values are, well, the values), insert a row in the table.
50              
51             If you need any of the values to be interpolated straight into the SQL, for
52             instance if you need to use a function call like C or similar, then you
53             can provide them as a scalarref:
54              
55             database->quick_insert('mytable', { foo => 'Bar', timestamp => \'NOW()' });
56              
57             Of course, if you do that, you must be careful to avoid SQL injection attacks!
58             =cut
59              
60             sub quick_insert {
61 0     0 1 0 my ($self, $table_name, $data) = @_;
62 0         0 return $self->_quick_query('INSERT', $table_name, $data);
63             }
64              
65             =item quick_update
66              
67             database->quick_update('mytable', { id => 42 }, { foo => 'Baz' });
68              
69             Given a table name, a hashref describing a where clause and a hashref of
70             changes, update a row.
71              
72             As per quick_insert, if you need any of the values to be interpolated straight
73             in the SQL, for e.g. to use a function call, provide a scalarref:
74              
75             database->quick_update('mytable', { id => 42 }, { counter => \'counter + 1' });
76              
77             Of course, if you do that, you must be careful to avoid SQL injection attacks!
78              
79             =cut
80              
81             sub quick_update {
82 0     0 1 0 my ($self, $table_name, $where, $data) = @_;
83 0         0 return $self->_quick_query('UPDATE', $table_name, $data, $where);
84             }
85              
86              
87             =item quick_delete
88              
89             database->quick_delete($table, { id => 42 });
90              
91             Given a table name and a hashref to describe the rows which should be deleted
92             (the where clause - see below for further details), delete them.
93              
94             =cut
95              
96             sub quick_delete {
97 0     0 1 0 my ($self, $table_name, $where) = @_;
98 0         0 return $self->_quick_query('DELETE', $table_name, undef, $where);
99             }
100              
101              
102             =item quick_select
103              
104             my $row = database->quick_select($table, { id => 42 });
105             my @rows = database->quick_select($table, { id => 42 });
106              
107             Given a table name and a hashref of where clauses (see below for explanation),
108             and an optional hashref of options, returns either the first matching
109             row as a hashref if called in scalar context, or a list of matching rows
110             as hashrefs if called in list context. The third argument is a hashref of
111             options to allow additional control, as documented below. For backwards
112             compatibility, it can also be an arrayref of column names, which acts in the
113             same way as the C option.
114              
115             The options you can provide are:
116              
117             =over 4
118              
119             =item C
120              
121             An arrayref of column names to return, if you only want certain columns returned
122              
123             =item C
124              
125             Specify how the results should be ordered. This option can take various values:
126              
127             =over 4
128              
129             =item * a straight scalar or arrayref sorts by the given column(s):
130              
131             { order_by => 'foo' } # equivalent to "ORDER BY foo"
132             { order_by => [ qw(foo bar) ] } # equiv to "ORDER BY foo,bar"
133              
134             =item * a hashref of C column name>, e.g.:
135              
136             { order_by => { desc => 'foo' } } # equiv to ORDER BY foo DESC
137             { order_by => [ { desc => 'foo' }, { asc => 'bar' } ] }
138             # above is equiv to ORDER BY foo DESC, bar ASC
139              
140             =back
141              
142             =item C
143              
144             Limit how many records will be returned; equivalent to e.g. C in an SQL
145             query. If called in scalar context, an implicit LIMIT 1 will be added to the
146             query anyway, so you needn't add it yourself.
147              
148             An example of using options to control the results you get back:
149              
150             # Get the name & phone number of the 10 highest-paid men:
151             database->quick_select(
152             'employees',
153             { gender => 'male' },
154             { order_by => 'salary', limit => 10, columns => [qw(name phone)] }
155             );
156              
157             =cut
158              
159             =item C number
160              
161             C says to skip that many rows before beginning to return rows (postgresql).
162              
163              
164             Example:
165              
166             # Get the name & phone number of the 10 highest-paid men starting from 11th:
167             database->quick_select(
168             'employees',
169             { gender => 'male' },
170             { order_by => 'salary', offset => 10, limit => 10, columns => [qw(name phone)] }
171             );
172              
173              
174             =cut
175              
176             sub quick_select {
177 0     0 1 0 my ($self, $table_name, $where, $opts) = @_;
178              
179             # For backwards compatibility, accept an arrayref of column names as the 3rd
180             # arg, instead of an arrayref of options:
181 0 0 0     0 if ($opts && ref $opts eq 'ARRAY') {
182 0         0 $opts = { columns => $opts };
183             }
184              
185             # Make sure to call _quick_query in the same context we were called.
186             # This is a little ugly, rewrite this perhaps.
187 0 0       0 if (wantarray) {
188 0         0 return ($self->_quick_query('SELECT', $table_name, $opts, $where));
189             } else {
190 0         0 return $self->_quick_query('SELECT', $table_name, $opts, $where);
191             }
192             }
193              
194             =back
195              
196             =item quick_lookup
197              
198             my $id = database->quick_lookup($table, { email => $params->{'email'} }, 'userid' );
199              
200             This is a bit of syntactic sugar when you just want to lookup a specific
201             field, such as when you're converting an email address to a userid (say
202             during a login handler.)
203              
204             This call always returns a single scalar value, not a hashref of the
205             entire row (or partial row) like most of the other methods in this library.
206              
207             Returns undef when there's no matching row or no such field found in
208             the results.
209              
210             =cut
211              
212             sub quick_lookup {
213 0     0 1 0 my ($self, $table_name, $where, $data) = @_;
214 0         0 my $opts = { columns => [$data] };
215 0         0 my $row = $self->_quick_query('SELECT', $table_name, $opts, $where);
216              
217 0 0 0     0 return ( $row && exists $row->{$data} ) ? $row->{$data} : undef;
218             }
219              
220             =item quick_count
221              
222             my $count = database->quick_count($table,
223             { email => $params->{'email'} });
224              
225             This is syntactic sugar to return a count of all rows which match your
226             parameters, useful for pagination.
227              
228             This call always returns a single scalar value, not a hashref of the
229             entire row (or partial row) like most of the other methods in this
230             library.
231              
232             =cut
233              
234             sub quick_count {
235 0     0 1 0 my ($self, $table_name, $where) = @_;
236 0         0 my $opts = {}; #Options are irrelevant for a count.
237 0         0 my @row = $self->_quick_query('COUNT', $table_name, $opts, $where);
238              
239 0 0       0 return ( @row ) ? $row[0] : undef ;
240             }
241              
242             # The 3rd arg, $data, has a different meaning depending on the type of query
243             # (no, I don't like that much; I may refactor this soon to use named params).
244             # For INSERT/UPDATE queries, it'll be a hashref of field => value.
245             # For SELECT queries, it'll be a hashref of additional options.
246             # For DELETE queries, it's unused.
247             sub _quick_query {
248 0     0   0 my ($self, $type, $table_name, $data, $where) = @_;
249            
250             # Basic sanity checks first...
251 0 0       0 if ($type !~ m{^ (SELECT|INSERT|UPDATE|DELETE|COUNT) $}x) {
252 0         0 carp "Unrecognised query type $type!";
253 0         0 return;
254             }
255 0 0 0     0 if (!$table_name || ref $table_name) {
256 0         0 carp "Expected table name as a straight scalar";
257 0         0 return;
258             }
259 0 0 0     0 if (($type eq 'INSERT' || $type eq 'UPDATE')
      0        
      0        
260             && (!$data || ref $data ne 'HASH'))
261             {
262 0         0 carp "Expected a hashref of changes";
263 0         0 return;
264             }
265 0 0 0     0 if (($type =~ m{^ (SELECT|UPDATE|DELETE|COUNT) $}x)
266             && (!$where)) {
267 0         0 carp "Expected where conditions";
268 0         0 return;
269             }
270              
271             # OK, get the SQL we're going to need
272             # TODO: can we replace our own generation with e.g. SQL::Abstract? How much
273             # backwards-incompatible change would that incur?
274 0         0 my ($sql, @bind_params) = $self->_generate_sql(
275             $type, $table_name, $data, $where
276             );
277              
278              
279             # Dancer::Plugin::Database will have looked at the log_queries setting and
280             # stashed it away for us to see:
281 0 0       0 if ($self->{private_dancer_plugin_database}{log_queries}) {
282             $self->{private_dancer_plugin_database}{logger}->(debug =>
283             "Executing $type query $sql with params " . join ',',
284             map {
285 0 0       0 defined $_ ?
  0 0       0  
    0          
286             $_ =~ /^[[:ascii:]]+$/ ?
287             length $_ > 50 ? substr($_, 0, 47) . '...' : $_
288             : "[non-ASCII data not logged]" : 'undef'
289             } @bind_params
290             );
291             }
292              
293             # Select queries, in scalar context, return the first matching row; in list
294             # context, they return a list of matching rows.
295 0 0       0 if ($type eq 'SELECT') {
    0          
296 0 0       0 if (wantarray) {
297             return @{
298 0         0 $self->selectall_arrayref(
  0         0  
299             $sql, { Slice => {} }, @bind_params
300             )
301             };
302             } else {
303 0         0 return $self->selectrow_hashref($sql, undef, @bind_params);
304             }
305              
306             } elsif ($type eq 'COUNT') {
307 0         0 return $self->selectrow_array($sql, undef, @bind_params);
308             } else {
309             # INSERT/UPDATE/DELETE queries just return the result of DBI's do()
310 0         0 return $self->do($sql, undef, @bind_params);
311             }
312             }
313              
314             sub _generate_sql {
315 6     6   3096 my ($self, $type, $table_name, $data, $where) = @_;
316              
317 6         7 my $which_cols = '*';
318 6 100 100     25 my $opts = $type eq 'SELECT' && $data ? $data : {};
319 6 100       12 if ($opts->{columns}) {
320             my @cols = (ref $opts->{columns})
321 1         3 ? @{ $opts->{columns} }
322 1 50       4 : $opts->{columns} ;
323 1         2 $which_cols = join(',', map { $self->_quote_identifier($_) } @cols);
  2         17  
324             }
325              
326 6         18 $table_name = $self->_quote_identifier($table_name);
327 6         87 my @bind_params;
328              
329             my $sql = {
330             SELECT => "SELECT $which_cols FROM $table_name",
331             INSERT => "INSERT INTO $table_name ",
332             UPDATE => "UPDATE $table_name SET ",
333             DELETE => "DELETE FROM $table_name ",
334             COUNT => "SELECT COUNT(*) FROM $table_name",
335 6         28 }->{$type};
336 6 100       18 if ($type eq 'INSERT') {
337 1         1 my (@keys, @values);
338 1         4 for my $key (sort keys %$data) {
339 2         2 my $value = $data->{$key};
340 2         4 push @keys, $self->_quote_identifier($key);
341 2 100       28 if (ref $value eq 'SCALAR') {
342             # If it's a scalarref it goes in the SQL as it is; this is a
343             # potential SQL injection risk, but is documented as such - it
344             # allows the user to include arbitrary SQL, at their own risk.
345 1         2 push @values, $$value;
346             } else {
347 1         2 push @values, "?";
348 1         2 push @bind_params, $value;
349             }
350             }
351              
352 1         5 $sql .= sprintf "(%s) VALUES (%s)",
353             join(',', @keys), join(',', @values);
354             }
355              
356 6 100       12 if ($type eq 'UPDATE') {
357 1         1 my @sql;
358 1         4 for (sort keys %$data) {
359             push @sql, $self->_quote_identifier($_) . '=' .
360 2 100       4 (ref $data->{$_} eq 'SCALAR' ? ${$data->{$_}} : "?");
  1         17  
361 2 100       18 push @bind_params, $data->{$_} if (ref $data->{$_} ne 'SCALAR');
362             }
363 1         2 $sql .= join ',', @sql;
364             }
365              
366 6 100 66     36 if ($type eq 'UPDATE' || $type eq 'DELETE' || $type eq 'SELECT' || $type eq 'COUNT')
      100        
      66        
367             {
368 5 100       10 if ($where) {
369 3         6 my ($where_sql, @where_binds) = $self->generate_where_clauses( $where );
370 3 50       6 return unless $where_sql; # there was a problem
371 3         4 $sql .= " WHERE $where_sql";
372 3         4 push(@bind_params, @where_binds);
373             }
374             }
375             # Add an ORDER BY clause, if we want to:
376 6 50 33     14 if (exists $opts->{order_by} and defined $opts->{order_by}) {
377 0         0 $sql .= ' ' . $self->_build_order_by_clause($opts->{order_by});
378             }
379              
380              
381             # Add a LIMIT clause if we want to:
382 6 50 33     30 if (exists $opts->{limit} and defined $opts->{limit}) {
    50 66        
383 0         0 my $limit = $opts->{limit};
384 0         0 $limit =~ s/\s+//g;
385             # Check the limit clause is sane - just a number, or two numbers with a
386             # comma between (if using offset,limit )
387 0 0       0 if ($limit =~ m{ ^ \d+ (?: , \d+)? $ }x) {
388             # Checked for sanity above so safe to interpolate
389 0         0 $sql .= " LIMIT $limit";
390             } else {
391 0         0 die "Invalid LIMIT param $opts->{limit} !";
392             }
393             } elsif ($type eq 'SELECT' && !wantarray) {
394             # We're only returning one row in scalar context, so don't ask for any
395             # more than that
396 0         0 $sql .= " LIMIT 1";
397             }
398            
399 6 50 33     21 if (exists $opts->{offset} and defined $opts->{offset}) {
400 0         0 my $offset = $opts->{offset};
401 0         0 $offset =~ s/\s+//g;
402 0 0       0 if ($offset =~ /^\d+$/) {
403 0         0 $sql .= " OFFSET $offset";
404             } else {
405 0         0 die "Invalid OFFSET param $opts->{offset} !";
406             }
407             }
408 6         18 return ($sql, @bind_params);
409             }
410              
411             sub generate_where_clauses {
412 3     3 0 3 my ($self, $where) = @_;
413 3         3 my $sql = "";
414 3         3 my @bind_params;
415 3 100 66     15 if ($where && !ref $where) {
    50          
    0          
416 1         2 $sql .= $where;
417             } elsif ( ref $where eq 'HASH' ) {
418 2         3 my @stmts;
419 2         21 foreach my $k ( sort keys %$where ) {
420 3         4 my $v = $where->{$k};
421 3 50       7 if ( ref $v eq 'HASH' ) {
422 0         0 my $not = delete $v->{'not'};
423 0         0 while (my($op,$value) = each %$v ) {
424 0         0 my ($cond, $add_bind_param)
425             = $self->_get_where_sql_clause($op, $not, $value);
426 0         0 push @stmts, $self->_quote_identifier($k) . $cond;
427 0 0       0 push @bind_params, $v->{$op} if $add_bind_param;
428             }
429             } else {
430 3         4 my $clause .= $self->_quote_identifier($k);
431 3 50       61 if ( ! defined $v ) {
    50          
    0          
432 0         0 $clause .= ' IS NULL';
433             }
434             elsif ( ! ref $v ) {
435 3         4 $clause .= '=?';
436 3         6 push @bind_params, $v;
437             }
438             elsif ( ref $v eq 'ARRAY' ) {
439 0         0 $clause .= ' IN (' . (join ',', map { '?' } @$v) . ')';
  0         0  
440 0         0 push @bind_params, @$v;
441             }
442 3         5 push @stmts, $clause;
443             }
444             }
445 2 50       9 $sql .= join " AND ", @stmts if keys %$where;
446             } elsif (ref $where) {
447 0         0 carp "Can't handle ref " . ref $where . " for where";
448 0         0 return;
449             }
450 3         6 return ($sql, @bind_params);
451             }
452              
453              
454             sub _get_where_sql_clause {
455 0     0   0 my ($self, $op, $not, $value) = @_;
456              
457 0         0 $op = lc $op;
458              
459             # "IS" needs special-casing, as it will be either "IS NULL" or "IS NOT NULL"
460             # - there's no need to return a bind param for that.
461 0 0       0 if ($op eq 'is') {
462 0 0       0 if (defined $value) {
463 0         0 $self->{private_dancer_plugin_database}{logger}->(warning =>
464             "Using the 'IS' operator only makes sense to test for nullness,"
465             ." but a non-undef value was passed. Did you mean eq/ne?"
466             );
467             }
468 0 0       0 return $not ? 'IS NOT NULL' : 'IS NULL';
469             }
470              
471 0         0 my %st = (
472             'like' => ' LIKE ?',
473             'is' => ' IS ?',
474             'ge' => ' >= ?',
475             'gt' => ' > ?',
476             'le' => ' <= ?',
477             'lt' => ' < ?',
478             'eq' => ' = ?',
479             'ne' => ' != ?',
480             );
481              
482             # Return the appropriate SQL, and indicate that the value should be added to
483             # the bind params
484 0 0       0 return (($not ? ' NOT' . $st{$op} : $st{$op}), 1);
485             }
486              
487             # Given either a column name, or a hashref of e.g. { asc => 'colname' },
488             # or an arrayref of either, construct an ORDER BY clause (quoting col names)
489             # e.g.:
490             # 'foo' => ORDER BY foo
491             # { asc => 'foo' } => ORDER BY foo ASC
492             # ['foo', 'bar'] => ORDER BY foo, bar
493             # [ { asc => 'foo' }, { desc => 'bar' } ]
494             # => 'ORDER BY foo ASC, bar DESC
495             sub _build_order_by_clause {
496 4     4   3187 my ($self, $in) = @_;
497              
498             # Input could be a straight scalar, or a hashref, or an arrayref of either
499             # straight scalars or hashrefs. Turn a straight scalar into an arrayref to
500             # avoid repeating ourselves.
501 4 100       15 $in = [ $in ] unless ref $in eq 'ARRAY';
502              
503             # Now, for each of the fields given, add them to the clause
504 4         3 my @sort_fields;
505 4         6 for my $field (@$in) {
506 6 100       45 if (!ref $field) {
    50          
507 3         7 push @sort_fields, $self->_quote_identifier($field);
508             } elsif (ref $field eq 'HASH') {
509 3         6 my ($order, $name) = %$field;
510 3         6 $order = uc $order;
511 3 50 66     11 if ($order ne 'ASC' && $order ne 'DESC') {
512 0         0 die "Invalid sort order $order used in order_by option!";
513             }
514             # $order has been checked to be 'ASC' or 'DESC' above, so safe to
515             # interpolate
516 3         6 push @sort_fields, $self->_quote_identifier($name) . " $order";
517             }
518             }
519              
520 4         85 return "ORDER BY " . join ', ', @sort_fields;
521             }
522              
523             # A wrapper around DBI's quote_identifier which first splits on ".", so that
524             # e.g. database.table gets quoted as `database`.`table`, not `database.table`
525             sub _quote_identifier {
526 23     23   502 my ($self, $identifier) = @_;
527              
528             return join '.', map {
529 23         38 $self->quote_identifier($_)
  24         86  
530             } split /\./, $identifier;
531             }
532              
533             =back
534              
535             All of the convenience methods provided take care to quote table and column
536             names using DBI's C, and use parameterised queries to avoid
537             SQL injection attacks. See L for why this is
538             important, if you're not familiar with it.
539              
540              
541             =head1 WHERE clauses as hashrefs
542              
543             C, C and C take a hashref of WHERE
544             clauses. This is a hashref of field => 'value', each of which will be
545             included in the WHERE clause used, for instance:
546              
547             { id => 42 }
548              
549             Will result in an SQL query which would include:
550              
551             WHERE id = 42
552              
553             When more than one field => value pair is given, they will be ANDed together:
554              
555             { foo => 'Bar', bar => 'Baz' }
556              
557             Will result in:
558              
559             WHERE foo = 'Bar' AND bar = 'Baz'
560              
561             (Actually, parameterised queries will be used, with placeholders, so SQL
562             injection attacks will not work, but it's easier to illustrate as though the
563             values were interpolated directly. Don't worry, they're not.)
564              
565             With the same idea in mind, you can check if a value is NULL with:
566              
567             { foo => undef }
568              
569             This will be correctly rewritten to C.
570              
571             You can pass an empty hashref if you want all rows, e.g.:
572              
573             database->quick_select('mytable', {});
574              
575             ... is the same as C<"SELECT * FROM 'mytable'">
576              
577             If you pass in an arrayref as the value, you can get a set clause as in the
578             following example:
579              
580             { foo => [ 'bar', 'baz', 'quux' ] }
581              
582             ... it's the same as C
583              
584             If you need additional flexibility, you can build fairly complex where
585             clauses by passing a hashref of condition operators and values as the
586             value to the column field key.
587              
588             Currently recognized operators are:
589              
590             =over
591              
592             =item 'like'
593              
594             { foo => { 'like' => '%bar%' } }
595              
596             ... same as C
597              
598             =item 'gt' / 'ge'
599              
600             'greater than' or 'greater or equal to'
601            
602             { foo => { 'ge' => '42' } }
603              
604             ... same as C= '42'>
605              
606             =item 'lt' / 'le'
607              
608             'less than' or 'less or equal to'
609              
610             { foo => { 'lt' => '42' } }
611              
612             ... same as C '42'>
613              
614             =item 'eq' / 'ne' / 'is'
615              
616             'equal' or 'not equal' or 'is'
617              
618             { foo => { 'ne' => 'bar' } }
619              
620             ... same as C
621              
622             =back
623              
624             You can also include a key named 'not' with a true value in the hashref
625             which will (attempt) to negate the other operator(s).
626              
627             { foo => { 'like' => '%bar%', 'not' => 1 } }
628              
629             ... same as C
630              
631             If you use undef as the value for an operator hashref it will be
632             replaced with 'NULL' in the query.
633              
634             If that's not flexible enough, you can pass in your own scalar WHERE clause
635             string B there's no automatic sanitation on that - if you suffer
636             from a SQL injection attack - don't blame me!
637             Don't forget to use C/C on it then.
638              
639             =head1 AUTHOR
640              
641             David Precious C< <> >
642              
643             =head1 ACKNOWLEDGEMENTS
644              
645             See L
646              
647             =head1 SEE ALSO
648              
649             L and L
650              
651             L and L
652              
653             L
654              
655             =head1 LICENSE AND COPYRIGHT
656              
657             Copyright 2016 David Precious.
658              
659             This program is free software; you can redistribute it and/or modify it
660             under the terms of the the Artistic License (2.0). You may obtain a
661             copy of the full license at:
662              
663             L
664              
665             Any use, modification, and distribution of the Standard or Modified
666             Versions is governed by this Artistic License. By using, modifying or
667             distributing the Package, you accept this license. Do not use, modify,
668             or distribute the Package, if you do not accept this license.
669              
670             If your Modified Version has been derived from a Modified Version made
671             by someone other than you, you are nevertheless required to ensure that
672             your Modified Version complies with the requirements of this license.
673              
674             This license does not grant you the right to use any trademark, service
675             mark, tradename, or logo of the Copyright Holder.
676              
677             This license includes the non-exclusive, worldwide, free-of-charge
678             patent license to make, have made, use, er to sell, sell, import and
679             otherwise transfer the Package with respect to any patent claims
680             licensable by the Copyright Holder that are necessarily infringed by the
681             Package. If you institute patent litigation (including a cross-claim or
682             counterclaim) against any party alleging that the Package constitutes
683             direct or contributory patent infringement, then this Artistic License
684             to you shall terminate on the date that such litigation is filed.
685              
686             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
687             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
688             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
689             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
690             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
691             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
692             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
693             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
694              
695             =cut
696              
697             1;
698             __END__