Author: byterock
Date: Wed Feb  6 10:37:45 2008
New Revision: 10698

Added:
   dbd-oracle/trunk/t/12impdata.t
   dbd-oracle/trunk/t/14threads.t
Modified:
   dbd-oracle/trunk/Oracle.pm
   dbd-oracle/trunk/dbdimp.c

Log:
Patch from Jeffrey Klein for dbi_imp_data code 

Modified: dbd-oracle/trunk/Oracle.pm
==============================================================================
--- dbd-oracle/trunk/Oracle.pm  (original)
+++ dbd-oracle/trunk/Oracle.pm  Wed Feb  6 10:37:45 2008
@@ -212,6 +212,7 @@
         (my $user_only = $user) =~ s:/.*::;
        my ($dbh, $dbh_inner) = DBI::_new_dbh($drh, {
            'Name' => $dbname,
+           'dbi_imp_data' => $attr->{dbi_imp_data},
            # these two are just for backwards compatibility
            'USER' => uc $user_only, 'CURRENT_USER' => uc $user_only,
            });

Modified: dbd-oracle/trunk/dbdimp.c
==============================================================================
--- dbd-oracle/trunk/dbdimp.c   (original)
+++ dbd-oracle/trunk/dbdimp.c   Wed Feb  6 10:37:45 2008
@@ -336,7 +336,22 @@
     D_imp_drh_from_dbh;
     ub2 new_charsetid = 0;
     ub2 new_ncharsetid = 0;
+    /* dbi_imp_data code adapted from DBD::mysql */
 
+    if (DBIc_has(imp_dbh, DBIcf_IMPSET)) {
+        /* dbi_imp_data from take_imp_data */
+        if (DBIc_has(imp_dbh, DBIcf_ACTIVE)) {
+            if (DBIS->debug >= 2)
+                PerlIO_printf(DBILOGFP, "dbd_db_login6 skip connect\n");
+            /* tell our parent we've adopted an active child */
+            ++DBIc_ACTIVE_KIDS(DBIc_PARENT_COM(imp_dbh));
+            return 1;
+        }
+        /* not ACTIVE so connect not skipped */
+        if (DBIS->debug >= 2)
+           PerlIO_printf(DBILOGFP,
+               "dbd_db_login6 IMPSET but not ACTIVE so connect not skipped\n");
+    }
     imp_dbh->envhp = imp_drh->envhp;   /* will be NULL on first connect */
 
 #if defined(USE_ITHREADS) && defined(PERL_MAGIC_shared_scalar)
@@ -2559,14 +2574,14 @@
                         (phs->ftype == ORA_NUMBER_TABLE)) {
                        /* Supported *
                    }else{*/
-                               /* All the other types are not supported 
+                               /* All the other types are not supported
                                croak("Array bind is supported only for 
ORA_%_TABLE types. Unable to bind '%s'.",phs->name);
                    /*}
                }*./
-               
-               
+
+
        /* Add checks for other reference types here ? */
-    
+
     phs->maxlen = maxlen;              /* 0 if not inout               */
 
     if (!is_inout) {   /* normal bind so take a (new) copy of current value    
*/
@@ -2595,7 +2610,7 @@
        dTHX;
        char *note = "";
     /* XXX doesn't check arcode for error, caller is expected to */
-  
+
     if (phs->indp == 0) {                       /* is okay      */
 
                if (phs->is_inout && phs->alen == SvLEN(sv)) {

Added: dbd-oracle/trunk/t/12impdata.t
==============================================================================
--- (empty file)
+++ dbd-oracle/trunk/t/12impdata.t      Wed Feb  6 10:37:45 2008
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+$| = 1;
+
+## ----------------------------------------------------------------------------
+## 12imptdata.t
+## By Jeffrey Klein, 
+## ----------------------------------------------------------------------------
+
+use strict;
+use DBI;
+use Config qw(%Config);
+BEGIN { eval "use threads; use threads::shared;" }
+my $use_threads_err = $@;
+use Test::More;
+
+BEGIN {
+    if ($DBI::VERSION <= 1.601){
+      plan skip_all => "DBI version ".$DBI::VERSION." does not supprt iThreads 
use version 1.602 or later";
+    }
+    die $use_threads_err if $use_threads_err;    # need threads
+}
+
+use Test::More tests => 7;
+
+unshift @INC, 't';
+require 'nchar_test_lib.pl';
+
+my $dsn    = oracle_test_dsn();
+my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger';
+my $dbh    = DBI->connect( $dsn, $dbuser, '', );
+
+my $drh = $dbh->{Driver};
+my ($sess_1) = $dbh->selectrow_array("select userenv('sessionid') from dual");
+
+is $drh->{Kids},       1, "1 kid";
+is $drh->{ActiveKids}, 1, "1 active kid";
+
+my $imp_data = $dbh->take_imp_data;
+is $drh->{Kids},       0, "no kids";
+is $drh->{ActiveKids}, 0, "no active kids";
+
+$dbh = DBI->connect( $dsn, $dbuser, '', { dbi_imp_data => $imp_data } );
+my ($sess_2) = $dbh->selectrow_array("select userenv('sessionid') from dual");
+is $sess_1, $sess_2, "got same session";
+
+is $drh->{Kids},       1, "1 kid";
+is $drh->{ActiveKids}, 1, "1 active kid";
+
+__END__

Added: dbd-oracle/trunk/t/14threads.t
==============================================================================
--- (empty file)
+++ dbd-oracle/trunk/t/14threads.t      Wed Feb  6 10:37:45 2008
@@ -0,0 +1,172 @@
+#!/usr/bin/perl
+$| = 1;
+
+## ----------------------------------------------------------------------------
+## 14threads.t
+## By Jeffrey Klein, 
+## ----------------------------------------------------------------------------
+
+BEGIN { eval "use threads; use threads::shared;" }
+my $use_threads_err = $@;
+use DBI;
+use Config qw(%Config);
+use Test::More;
+
+BEGIN {
+    if ( !$Config{useithreads} || $] < 5.008 ) {
+        plan skip_all => "this $^O perl $] not configured to support iThreads";
+    } elsif ($DBI::VERSION <= 1.601){
+      plan skip_all => "DBI version ".$DBI::VERSION." does not supprt iThreads 
use version 1.602 or later";
+     }
+    die $use_threads_err if $use_threads_err;    # need threads
+}
+
+use strict;
+use DBI;
+
+use Test::More tests => 19;
+
+unshift @INC, 't';
+require 'nchar_test_lib.pl';
+
+my $last_session : shared;
+our @pool : shared;
+
+# run five threads in sequence
+# each should get the same session
+
+# TESTS: 5
+
+for my $i ( 0 .. 4 ) {
+    threads->create(
+        sub {
+            my $dbh = get_dbh_from_pool();
+
+            my $session = session_id($dbh);
+
+            if ( $i > 0 ) {
+                is $session, $last_session,
+                  "session $i matches previous session";
+            } else {
+                ok $session, "session $i created",
+            }
+
+            $last_session = $session;
+            free_dbh_to_pool($dbh);
+        }
+    )->join;
+}
+
+# TESTS: 1
+is scalar(@pool), 1, 'one imp_data in pool';
+
+# get two sessions in same thread
+# TESTS: 2
+threads->create(
+    sub {
+        my $dbh1 = get_dbh_from_pool();
+        my $s1   = session_id($dbh1);
+
+        my $dbh2 = get_dbh_from_pool();
+        my $s2   = session_id($dbh2);
+
+        ok $s1 ne $s2, 'thread gets two separate sessions';
+
+        free_dbh_to_pool($dbh1);
+
+        my $dbh3 = get_dbh_from_pool();
+        my $s3   = session_id($dbh3);
+
+        is $s3, $s1, 'get same session after free';
+
+        free_dbh_to_pool($dbh2);
+        free_dbh_to_pool($dbh3);
+    }
+)->join;
+
+# TESTS: 1
+is scalar(@pool), 2, 'two imp_data in pool';
+
+#trade dbh between threads
+my @thr;
+my @sem;
+use Thread::Semaphore;
+
+# create locked semaphores
+for my $i (0..2) {
+   push @sem, Thread::Semaphore->new(0);
+}
+
+undef $last_session;
+
+# 3 threads, 3 iterations
+# TESTS: 9
+for my $t ( 0..2 ) {
+    $thr[$t] = threads->create(
+        sub {
+            my $partner = ( $t + 1 ) % 3;
+
+            for my $i ( 1 .. 3 ) {
+                $sem[$t]->down;
+
+                my $dbh     = get_dbh_from_pool();
+                my $session = session_id($dbh);
+                if ( defined $last_session ) {
+                    is $session, $last_session,
+                      "thread $t, loop $i matches previous session";
+                } else {
+                    ok $session,
+                      "thread $t, loop $i created session";
+                }
+                $last_session = $session;
+                free_dbh_to_pool($dbh);
+
+                # signal next thread
+                $sem[$partner]->up;
+            }
+        }
+    );
+}
+
+# start thread 0!
+$sem[0]->up;
+
+$_->join for @thr;
+
+# TESTS: 1
+empty_pool();
+
+is scalar(@pool), 0, 'pool empty';
+
+exit;
+
+sub get_dbh_from_pool {
+    my $imp = pop @pool;
+
+    # if pool is empty, $imp is undef
+    # in that case, get new dbh
+    return connect_dbh($imp);
+}
+
+sub free_dbh_to_pool {
+    my $imp = $_[0]->take_imp_data or return;
+    push @pool, $imp;
+}
+
+sub empty_pool {
+    get_dbh_from_pool() while @pool;
+}
+
+sub connect_dbh {
+    my $imp_data = shift;
+    my $dsn      = oracle_test_dsn();
+    my $dbuser   = $ENV{ORACLE_USERID} || 'scott/tiger';
+    DBI->connect( $dsn, $dbuser, '', { dbi_imp_data => $imp_data } );
+}
+
+sub session_id {
+    my $dbh = shift;
+    my ($s) = $dbh->selectrow_array("select userenv('sessionid') from dual");
+    return $s;
+}
+__END__

Reply via email to