PEPPLER.ORG
Michael Peppler
Sybase Consulting
Menu
Home
Sybase on Linux
Install Guide for Sybase on Linux
General Sybase Resources
General Perl Resources
Freeware
Sybperl
Sybase::Simple
DBD::Sybase
BCP Tool
Bug Tracker
Mailing List Archive
Downloads Directory
FAQs
Sybase on Linux FAQ
Sybperl FAQ
Personal
Michael Peppler's resume

sybperl-l Archive

Up    Prev    Next    

From: Michael Peppler <mpeppler at MBAY dot NET>
Subject: Re: Handling multiple result sets
Date: Sep 5 1997 9:45PM

Tim Bunce wrote:
> 
> > From: Michael Peppler 
> >
> > Hi!
> 
> Hi Michael.
> 
> > I've finally started work on the real DBD::Sybase module, and I've run
> > into a problem which I suspect others have solved before me.
> 
> Nope. It's Sybase specific.

Oh well - we'll do some experimenting then :-)

> 
> > Sybase allows the following SQL syntax:
> >
> > SELECT select_list FROM table WHERE condition ORDER BY clause
> > COMPUTE aggregate expression BY column
> >

Here's what Sybase returns for this query in isql (the interactive,
command line interface):

1> select id, convert(char(10), log_by), log_date from BugTrack..bug_log
where id < 5 order by id compute count(id) by id
2> go
 id                     log_date                   
 ----------- ---------- -------------------------- 
           2 mpeppler          Feb 17 1995  3:45PM 
           2 mpeppler          Feb 17 1995  3:48PM 
           2 mpeppler          Feb 17 1995  4:07PM 
           2 mpeppler          Feb 17 1995  4:15PM 
 count                                             
 -----------                                       
           4                                       

 id                     log_date                   
 ----------- ---------- -------------------------- 
           3 mpeppler          Apr 19 1995 11:21AM 
 count                                             
 -----------                                       
           1                                       

 id                     log_date                   
 ----------- ---------- -------------------------- 
           4 mpeppler          Apr 19 1995 11:21AM 
 count                                             
 -----------                                       
           1                                       

(9 rows affected)
1> 

As you can see, the row count is the count of the *normal* rows returned
by the query. The compute by rows are additional rows.

> 
> How do you deal with meta-data like the number of fields or the data type
> of each field? I presume each time round the loop all that meta data
> can change.

Yes.

In this case, the Sybase::CTlib module would look like this:

$dbh->ct_execute("
select id, log_by, log_date from BugTrack..bug_log where id < 5 order by
id compute count(id) by id
");

while($dbh->ct_results($restype) == CS_SUCCEED) {
    print "restype = $restype\n";
    if($dbh->ct_fetchable($restype)) {
	print "fetchable data:\n";
	while(@dat = $dbh->ct_fetch) {
	    print "\t@dat\n";
	}
    }
    print "Rows: ", $dbh->ct_res_info(CS_ROW_COUNT), "\n" 
	if $restype == CS_CMD_DONE;
}

Which gives the following (truncated) output:

kiruna (2:34pm):10 > perl ct.pl
restype = 4040
fetchable data:
	2 mpeppler Feb 17 1995  3:45:30:750PM
	2 mpeppler Feb 17 1995  3:48:39:756PM
	2 mpeppler Feb 17 1995  4:07:38:723PM
	2 mpeppler Feb 17 1995  4:15:02:040PM
restype = 4045
fetchable data:
	4

(etc...)

restype = 4040
fetchable data:
	4 mpeppler Apr 19 1995 11:21:49:690AM
restype = 4045
fetchable data:
	1
restype = 4046
Rows: 9


As you see, sending a query with a compute by clause causes the 
result set to be broken up. This is different from executing a
stored proc that contains to SELECT clauses, both of which need to 
be processed (which again is perfectly valid in Transact SQL).

> 
> > I talked about this briefly with Tim B. at the Perl Conference, and
> > he came up with the idea of having $sth->fetch() return an empty row,
> 
> i.e. Look like the end of the data - to represent here the end of a data set.
> 
> > so that it could be called again to get the next result set.
> > Another way would be to make $dbh->execute retryable, though I
> > don't know if that would break the DBI specs.
> 
> What do you mean by retryable?

I was thinking of being able to call $sth->execute again to get
the next result set. I don't know if this is valid DBI code:
while($sth->execute) {
	while(@dat = $sth->fetch) {
		do something here...
	}
}
$sth->finish;

I sort of doubt it...

> 
> > Comments and suggestions are welcome!
> 
> The only problem that I can see with the $sth->fetch approach is the
> timing of the change in meta-data values.
> 
>         $sth->fetch;    # returns last row of data set 1
>         # point A
>         $sth->fetch;    # returns nothing (end of data set)
>         # point B
>         $sth->fetch;    # returns first row of data set 2
>         # point C
> 
> At what point should $sth->{NUM_OF_ROWS} change?

As shown in the example above, $sth->{NUM_OF_ROWS} is really only
set after the entire query has been processed (at least in Sybase's
view). We could of course change that and set it after each sub-set.

Michael
-- 
Michael Peppler       -||-  Data Migrations Inc.
mpeppler@datamig.com  -||-  http://www.mbay.net/~mpeppler