\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7<F<2PFAFZUP_xxnnx\F5\AF\B9\91\C8\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\DB\00CUZZxix‚\EB\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\C0\00\00b\00d\00\FF\C4\00\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\C4\00\00\00\00\00\00\00\00\00\00\001A!Q\FF\C4\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\C4\00\00\00\00\00\00\00\00\00\00!1AQ\FF\DA\00\00\00?\00\F6\00\00\00\00\00\00\00\00\00\00\A0\00\00\C5\CF\F8\E7Ó\FCjD~\B9^\AD\%\B3]\D8cs-\BBs,-\A0\00"\80\00%\B83rÏ^K~F\A4ea\00E\00\C6\EE=u\B1\9B\D1\00@\00r\BE8\F9:\FE5#.M\00\E7\CB\C9q\CBq\D6\F2\BE\B7\C7>\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7	\8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh
\00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€
\00$\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95
59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>C///</title>
</head>
package DBI::Gofer::Request;

#   $Id: Request.pm 12536 2009-02-24 22:37:09Z Tim $
#
#   Copyright (c) 2007, Tim Bunce, Ireland
#
#   You may distribute under the terms of either the GNU General Public
#   License or the Artistic License, as specified in the Perl README file.

use strict;

use DBI qw(neat neat_list);

use base qw(DBI::Util::_accessor);

our $VERSION = sprintf("0.%06d", q$Revision: 12536 $ =~ /(\d+)/o);

use constant GOf_REQUEST_IDEMPOTENT => 0x0001;
use constant GOf_REQUEST_READONLY   => 0x0002;

our @EXPORT = qw(GOf_REQUEST_IDEMPOTENT GOf_REQUEST_READONLY);


__PACKAGE__->mk_accessors(qw(
    version
    flags
    dbh_connect_call
    dbh_method_call
    dbh_attributes
    dbh_last_insert_id_args
    sth_method_calls
    sth_result_attr
));
__PACKAGE__->mk_accessors_using(make_accessor_autoviv_hashref => qw(
    meta
));


sub new {
    my ($self, $args) = @_;
    $args->{version} ||= $VERSION;
    return $self->SUPER::new($args);
}


sub reset {
    my ($self, $flags) = @_;
    # remove everything except connect and version
    %$self = (
        version => $self->{version},
        dbh_connect_call => $self->{dbh_connect_call},
    );
    $self->{flags} = $flags if $flags;
}


sub init_request {
    my ($self, $method_and_args, $dbh) = @_;
    $self->reset( $dbh->{ReadOnly} ? GOf_REQUEST_READONLY : 0 );
    $self->dbh_method_call($method_and_args);
}


sub is_sth_request {
    return shift->{sth_result_attr};
}


sub statements {
    my $self = shift;
    my @statements;
    if (my $dbh_method_call = $self->dbh_method_call) {
        my $statement_method_regex = qr/^(?:do|prepare)$/;
        my (undef, $method, $arg1) = @$dbh_method_call;
        push @statements, $arg1 if $method && $method =~ $statement_method_regex;
    }
    return @statements;
}


sub is_idempotent {
    my $self = shift;

    if (my $flags = $self->flags) {
        return 1 if $flags & (GOf_REQUEST_IDEMPOTENT|GOf_REQUEST_READONLY);
    }

    # else check if all statements are SELECT statement that don't include FOR UPDATE
    my @statements = $self->statements;
    # XXX this is very minimal for now, doesn't even allow comments before the select
    # (and can't ever work for "exec stored_procedure_name" kinds of statements)
    # XXX it also doesn't deal with multiple statements: prepare("select foo; update bar")
    return 1 if @statements == grep {
                m/^ \s* SELECT \b /xmsi && !m/ \b FOR \s+ UPDATE \b /xmsi
             } @statements;

    return 0;
}


sub summary_as_text {
    my $self = shift;
    my ($context) = @_;
    my @s = '';

    if ($context && %$context) {
        my @keys = sort keys %$context;
        push @s, join(", ", map { "$_=>".$context->{$_} } @keys);
    }

    my ($method, $dsn, $user, $pass, $attr) = @{ $self->dbh_connect_call };
    $method ||= 'connect_cached';
    $pass = '***' if defined $pass;
    my $tmp = '';
    if ($attr) { 
        $tmp = { %{$attr||{}} }; # copy so we can edit
        $tmp->{Password} = '***' if exists $tmp->{Password};
        $tmp = "{ ".neat_list([ %$tmp ])." }";
    }
    push @s, sprintf "dbh= $method(%s, %s)", neat_list([$dsn, $user, $pass]), $tmp;

    if (my $flags = $self->flags) {
        push @s, sprintf "flags: 0x%x", $flags;
    }

    if (my $dbh_attr = $self->dbh_attributes) {
        push @s, sprintf "dbh->FETCH: %s", @$dbh_attr
            if @$dbh_attr;
    }

    my ($wantarray, $meth, @args) = @{ $self->dbh_method_call };
    my $args = neat_list(\@args);
    $args =~ s/\n