Jeff,

I've been busy but finally managed to test the new version. It still 
fails my test.

Jeff Urlwin wrote:

>Roger,
>
>I've finally had a chance to look at this (going through my queue of issues
>& questions).  What I can see is the following:
>       - No result columns are being returned
>
In my case there isn't a query running.

>       - DBD::ODBC calls SQLMoreResults (and gets SQL_SUCCESS_WITH_INFO) to skip
>over the empty result set
>       - There are no more results, so execute() returns
>       - then, the call to NUM_OF_FIELDS triggers a "describe"
>
By "describe" you mean SQLDescribeCol, right? Where does the parameter 
value come from? I'm calling the procedure with the parameter set to -1 
(which doesn't produce a resultset) but SQLDescribeCol uses 0 which does 
produce a resultset. (See the SQL Profiler text below)

Why does the call to NUM_OF_FIELDS trigger a describe? Doesn't the call 
to execute provide the necesarry information?

Copied from BOL:
For executed statements, the Microsoft® SQL Server™ ODBC driver does not 
need to query the server to describe columns in a result set. In this 
case, SQLDescribeCol does not cause a server roundtrip.

The current implementation seems like a huge performance hog.

>       - to that, SQLServer returns a large description of columns (probably
>describing what would be the select * from systypes would have been.
>
>I would have thought it would not return anything at that point, other than
>there are no rows in the result set.
>
>I've fixed the problem/worked around it.  My tests pass here, but it's
>probably worth you testing further.
>
>Thanks for the find and the test!  I'm releasing _18 tonight.
>
Thanks for the update. Strange it didn't fix my problem. I rebooted my 
machine to make sure I wasn't using the old dll. I might have done some 
stupid error but ppm says I'm using 0.45_18. (Is there a way to see 
which version of the dll (not the module) Perl is using when the program 
is running?)

May I see your test for this specific case? I couldn't (easily) find it 
in http://search.cpan.org/src/JURL/DBD-ODBC-0.45_18/

>
>Regards,
>
>Jeff
>
>
>  
>
>>Hi,
>>
>>I've managed to produce a test case for the bug I reported earlier.
>>
>>When I call a stored procedure that should not return data
>>$sth->{NUM_OF_FIELDS} is wrong and I get the following error:
>>
>>E:\Projekt\Helpdesk\Perl\UpgradeDB>dbitest4.pl
>>$sth->{NUM_OF_FIELDS}: 18 expected: 0
>>DBD::ODBC::st fetchrow_hashref failed: (DBD: no select statement
>>currently executing err=-1) [for statement ``{call testPrc(?)}'' with
>>params: 1=-1]) at E:\Projekt\Helpdesk\Perl\UpgradeDB\DbiTest4.pl line 47.
>>
>>The problem is caused by the fact that the procedure is called with
>>different parameters when its output is examined (SET FMTONLY ON).
>>
>>Cut and paste from SQL Profiler:
>>Event Class           Text
>>+Connect
>>+ExistingConnection
>>+SQL:BatchStarting    set implicit_transactions on
>>+RPC:Starting         testPrc -1
>>+SP:Starting          testPrc
>>+SP:StmtStarting      if(@parameter1 >= 0)
>>+SP:StmtStarting      RETURN(@parameter1)
>>+SP:Completed         testPrc
>>+SQL:BatchStarting    SET FMTONLY ON  EXEC testPrc 0   SET FMTONLY OFF
>>+SP:Starting          testPrc
>>+SP:StmtStarting      if(@parameter1 >= 0)
>>+SP:StmtStarting      select * from systypes
>>+SP:StmtStarting      RETURN(@parameter1)
>>+SP:Completed         testPrc
>>+SQL:BatchStarting    IF @@TRANCOUNT > 0 ROLLBACK TRAN
>> Disconnect
>>
>>
>>    
>>

Cerate the testPrc procedure first and edit %options before you run.

============= Dbitest4.pl ====================
use strict;
use warnings;

use DBI;

use constant LONG_READ_LEN => 8000;

my %options = (
DbSrcServer => '(local)',
DbSrcDatabase => 'databaseName',
DbSrcLoginName => 'sa',
DbSrcPassword => '',
);

my @dbhPool;

##########################################
### Functions
##########################################

sub newDbh()
{ my $dbh;

if(defined($options{DbSrcServer}) && defined($options{DbSrcLoginName}) 
&& defined($options{DbSrcDatabase}))
{ my $dsn = "DRIVER={SQL 
Server};SERVER=$options{DbSrcServer};DATABASE=$options{DbSrcDatabase};NETWORK=dbmssocn;UID=$options{DbSrcLoginName};PWD=$options{DbSrcPassword}";
# print "DSN: $dsn\n\n";

$dbh = DBI->connect("DBI:ODBC:$dsn") || die "DBI connect failed: 
$DBI::errstr\n";
$dbh->{AutoCommit} = 0; # enable transactions, if possible
# $dbh->{RaiseError} = 0;
# $dbh->{PrintError} = 1; # use RaiseError instead
$dbh->{ShowErrorStatement} = 1;

push @dbhPool, $dbh;
return($dbh);
}
}


sub test()
{ my $dbh = newDbh();
my $sth = $dbh->prepare("{call testPrc(?)}");

$sth->bind_param(1, -1, { TYPE => 4 });
$sth->execute();

print '$sth->{NUM_OF_FIELDS}: ', $sth->{NUM_OF_FIELDS}, " expected: 0\n";
if($sth->{NUM_OF_FIELDS})
{ $sth->fetchrow_hashref('NAME');
}
}



##########################################
### Test
##########################################

test();

##########################################
### Cleanup...
##########################################

foreach my $dbh (@dbhPool)
{ $dbh->rollback();
$dbh->disconnect();
}


=========== testPrc.sql =======================
create PROCEDURE dbo.testPrc
@parameter1 int = 0
As

if(@parameter1 >= 0)
select * from systypes

-- RETURN(@parameter1)


Reply via email to