But it is not so difficult to implement queries with aggregate functions in C++ - just open a cursor, iterate through all records in the table and calculate correspondent function for the values of the particular field. Group-by queries also can be easily implemented using index for grouping field, selecting records in the order of increasing/decreasing values of this field and checking for duplicate values. Consider the following example: we have table containing information about students and we want to find the best student in each group (student in the group with the highest mark). One of the possible SQL versions of this query is the following:
select S1.name,S1.mark from Students S1 where S1.mark=(select max(S2.mark) from Student S2 where S2.GroupID=S1.GroupID group by S2.GroupID);This query is complex and inefficient at the same time and I am not sure that even the smartest optimizer can choose for this query execution plan which will be as efficient as algorithm expressed in imperative programming language mentioned below. Usually such queries are implemented in SQL using temporary table. But temporary table is not very standard approach and more important - by introducing temporary table and so splitting query into two subqueries we loose pure declarative semantic of query - now we explicitly specify steps which system should perform to execute our query. Object-oriented version of the query above is not significantly more complex than SQL statement but is certainly more efficient:
dbCursor<Student> students; if (students.select("order by group") != 0) { int maxMark =students.name; char studentName[256]; dbReference<Group> group = students.group; strcpy(studentName, students->name); while (students.next()) { if (students->group != group) { printf("name=%s, mark=%d\n", studentName, maxMark); group = students->group; maxMark =students->mark; strcpy(studentName, students->name); } else if (students->mark > maxMark) { maxMark =students->mark; strcpy(studentName, students->name); } } printf("name=%s, mark=%d\n", studentName, maxMark); }
There is also problem with reporting unique constraint violation conflict. Just returning error code is not goods idea. Insert method returns OID of created object and update method returns nothing. If insert will return invalid OID and update will return false, then first of all user can forgot to check this returned value, and second - it is not clear what is the source of the problem. Throwing exception is better idea, but exceptions are still bad supported in C++ (in some compilers exception support is switched off by default, some compiler generate a lot of extra code if exception support is enabled, some compiler doesn't correctly support exceptions at all. That is why support of exceptions in GigaBASE/FastDB is optional and it can not be used as mechanism of reporting queue constraint violation.
Also I want to notice that database in any case has to synchronize access to its internal structures. For example allocation of the object should be done in critical section. And as far as any update/insert/deletion of the record in GigaBASE/FastDB requires allocation of multiple objects, then you should realize that even if fine grain locking is used, transactions still have to compete for resources, and it can even cause performance degradation comparing with current scheme.
The main problem is actually duration of locking: to preserve transaction serialization locks are held until the end of transaction. It was intended that transactions will be mostly small and fast. As far a frequent commits cause multiple synchronized writes to the disk and as far as it is very expensive operation, performance can be awful. To solve the problem, GigaBASE/FastDB provides precommit method which release transaction locks but do not flush changes to the disk.
class A class B : that inherits from A class C : that inherits from A class D : that contains a reference on an A object.I want to have this> reference on a class A object but actually this object is a B or C object. Is that possible with FastDB ?
key1=? AND key2=? AND ...In this case GigaBASE will use index search for each key and them perform merge of the results.
GigaBASE doesn't support unique constraint - so you can insert duplicates in the index. If you want to prevent it, you should check first if such key is already present in the index.