[ZOOM] Re: zoom.hh

Mike Taylor mike at tecc.co.uk
Fri Nov 23 17:25:17 CET 2001


> Date: Fri, 23 Nov 2001 14:06:10 +0000
> From: Ashley Sanders <zzaascs at irwell.mimas.ac.uk>
> 
> Re: why did we change how resultSets are created.
> 
> 'cos it works better that way!

:-)

Come on, we can and must do better than that!  What am I going to say
in the rationale on the site?  Yes, the flexibility of constructors
that means we can use the to obtain either a foo or a foo* is a win:
but is that the _only_ win?  Is that what we did this for?

> > > I'm afraid getRecord still returns a pointer to const record and
> > > class record still has clone. I really can't see a sensible way
> > > around this -- but maybe I'm just being thick.
> > 
> > We'll discuss this separately when I've caught up.
> 
> Well, I was partly being a bit thick, but the main problem is that a
> reference to a record has to be returned, even when the origin
> wasn't able to retrieve a record.

OK, so this seems to be a reason for preferring pointers to references
in this content.  Is that all you're saying?

I'm addressing the (I think) more fundamental problem of whether a
record returned from getRecord() "belongs" to the result set or to the
application (or to someone else entirely.)

The obvious approach, and the one I have been advocating, is for the
record objects to be "autonomous", that is, not owned by or reliant on
anything -- so the application has to decallocate them when it's done.
This model allows you to write code like the following [untested!]:

	record *get_first_record (connection *c, query *q) {
	    resultSet rs(q);
	    if (rs->size() == 0) abort();
	    return rs->getRecord(0);
	}

And the returned record is valid, even though the result set from
which it was obtained has gone away -- implicitly destructed when it
went out of scope.

Now am I right in thinking that the main argument against this is that
we then can't write:

	void print_all_titles (connection *c, query *q) {
	    resultSet rs(c, q);
	    size_t n = rs->size();
	    for (size_t i = 0; i < n; i++)
		puts(rs->getRecord(i)->field("title");
	}

That's it, right?  We want to avoid having to say:

	    for (size_t i = 0; i < n; i++) {
	        record *r = rs->getRecord(i);
		puts(r->field("title");
		delete r;
	    }

I can see the appeal of the shorter version.  Just want to be sure I'm
not missing anything.

> So if we use references we also need some sort of error record.

I see -- an argument for returning pointers rather than references --
but I think this is orthogonal to whether or not the returned thing is
owned by its result set.

(Of course, if getRecord() returns a reference, we could always have
it throw an exception if an error occurs.  After all, we already do
this on connection failure, right?)

> In the tar ball I sent you I've created something called nullRecord
> for such a circumstance. I'd be happy to change the name to
> something else.

The name is not really an issue.  The whole concept is unappealling.
Though if we can't find anything better then, well, OK I suppose.

 _/|_	 _______________________________________________________________
/o ) \/  Mike Taylor   <mike at miketaylor.org.uk>   www.miketaylor.org.uk
)_v__/\  "Cold weather is God's way of telling us to burn more
	 Catholics" -- Richard Curtis, "Blackadder II".




More information about the ZOOM mailing list