Boost logo

Boost :

From: Corwin Joy (cjoy_at_[hidden])
Date: 2001-06-06 11:31:43

----- Original Message -----
From: "Bill Seymour" <bsey_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Wednesday, June 06, 2001 8:34 AM
Subject: Re: [boost] Interest in Database Template Library?

> I've looked over the _Introduction to the Database Template
> Library_ document, and I've reread about the first half more
> carefully. The second half hasn't sunk in yet.
> I have a few concerns:
> - I would recommend not overloading the == operator to bind
> database columns to structure members. In accordance with
> the "principle of least surprise," overloaded operators
> should do the same kind of thing that the corresponding
> built-in operators do. I suggest a conventional member
> function for doing the binding. The name "bind" comes
> to mind. 8-)

In general I strongly agree with you about the "principle of least
surprise". In this case, we felt that there was a good reason for
overloading operator == so here it is:
Rationale for operator ==:
1. Overloading == increases clarity:
When you invoke == on a binding column what you are really doing is creating
a kind of equivalence relation, hence

columns["EmployeeName"] == employee.EmpName;

creates an 'equivalence' between the database field called "EmployeeName"
and the member of the employee class/struct called EmpName. Here we say
this is an 'equivalence' because it is bidirectional in that data can be
either read from the database field into the class member or written from
the member back into the database. So in this sense we think that '==' is
intuitive in that it corresponds to frequently used notation for
equivalence. Saying that database fields are 'equivalent' to class members
in this way makes the relationship easy to understand. The other reason for
overloading this operator was readability. We considered the following
types of syntax but felt they made the binding routines harder to read which
becomes quite important as you move to tables with a larger number of



columns["EmployeeName"] == employee.EmpName;
columns["Salary"] == employee.Salary;
columns["DateOfBirth"] == employee.Birthday;


BIND(columns["EmployeeName], employee.EmpName);

2. Overloading == creates no surprises
For most classes, programmers don't expect operator == to have a meaning for
types other than the class itself. So, given that BoundIO is an internal
class progammers would not expect e.g.
BoundIO b;
b == string("hi");
b == int(5);
b == double(7.3);
to even compile so defining this operation to mean binding should not create

> - Without random-access iterators, it seems like there's
> no way to mimic the functionality of scroll cursors.
> They're part of standard SQL.

I think what you mean here is that scrollable cursors are common in APIs
that access databases (rather than part of SQL itself). Anyway, I agree, it
would be cool to have random access iterators that bind against scrollable
recordsets underneath. Our first pass, however, was to get simple forward
iterators versus a direct read / write against the database. We also have
random access capability in the IndexedDBView containers in that these are
multisets where you can pull up any element using an index. These are not
as efficient as a scrollable recordset, however, since they have to pre-load
the all the rows rather than working with a block at a time. (Also, I have
a bit of terror in providing a random access iterator for a table. What
does it mean to say e.g. row[20], given that there may not be any natural
ordering on the table, and that even if there is such an ordering the first
time you say row[20] you may get a different element from the second time
you say row[20] becuase someone else may have inserted a new element into
the table that your program doesn't know about. I would want to think about
this fairly carefully before I did it - especially since a lot of random
access algorithms may depend on size() being fixed during the course of the
algorithm which we can't guarantee here.).
> - What's the first DefaultInsValidate<>::operator() argument?
> It's not referenced in the sample code. Could it have
> something to do with validating a row based on values
> in other rows? If so, I think that violates the relational
> paradigm.
The requirements for an InsValidate functor is that it must provide the
following operator:
bool operator()(BoundIOs &boundIOs, DataObj &rowbuf)

The boundIOs argument is used to write status information for the row
indicating if any fields are NULL. The rowbuf consists of the individual
data row which is validated for correctness before it is allowed to be
written to the database. The return code indicates whether the row is valid
(true) or invalid (false) for purposes of writing this individual row to the
datase. For more, see our docs:

> - In the IndexedViewExample() function, it looks like the
> framework allows modifying keys. This seems dangerous.

The iterators we hand out are read only. The only way to modify to modify
an element in the container is through a replace(Iterator OldValue,
DataObject NewValue) method. Internally, as far as the multiset is
concerned, this will erase() the OldValue and insert() the new value. As
far as the databse is concerned this will execute an UPDATE statement to
update to old value to the new value. Internally, these two operations are
done so as to be jointly atomic, i.e. all or nothing for both operations.
> - There are several places in the document where it's implied
> that SGI documentation contains the authoritative description
> of the part of the C++ standard library commonly called the
> STL. I don't mean to cast any aspersions on CGI; but isn't
> the ISO standard a better authority to cite?
You're right -we should make it clear that the ISO standard is the authority
here. It is nice to provide a link, however, for definitions of containers
and so forth, since many people don't have a copy of the standard / know
where to look offhand.

Thanks for the comments.


Boost list run by bdawes at, gregod at, cpdaniel at, john at