OOFILE | Downloads | Purchasing | Press | Services | Company Information | Soapbox | References | F.A.Q. | HOME |
This sample demonstrates how to create an ad-hoc query.
#include "oofile.h" // the general oofile library #include "ooftst01.h" // the declarations for the database classes we will be using in this test.
These are two procedures we will define later. The first one takes in a set of search strings to look for and whether or not we wish the substrings to be ANDed or ORed together. It searches through the two fields of LastName and OtherNames.
void anyName(const char* searchStrings[], bool isOr, unsigned short numSch);
The second procedure does mostly the same thing but searches only through one field (lastNames) and ******* doesn't give the option to AND or OR the substrings together, they are all ????*ed
void lastName(const char* searchStrings[], unsigned short numSch);
******* This is a quickly defined piece of code to count how many entries there are in something I am not aware of yet
#define numEntries(A) sizeof(A)/sizeof(A[0])
Now we declare our database and table.
TEST_CONNECT theDB; dbPeople People;
int main()
{
cout << "OOFILE Validation Suite - Test 20\n"
<< "Demonstration of ad-hoc query building\n";
This is a bit of complicated filename logic to support different backends with this one test program
#ifdef TESTING_CTREE theDB.useSeparateFiles();
#ifdef _Macintosh const char* kExistsName = ":ooftst01:People.dat"; const char* kDatabaseName = ":ooftst01:"; #else const char* kExistsName = "People.dat" const char* kDatabaseName = ""; #endif
#else #ifdef TESTING_DBASE #ifdef _Macintosh const char* kExistsName = ":ooftst01:People.dbf"; const char* kDatabaseName = ":ooftst01:"; #else const char* kExistsName = "People.dbf" const char* kDatabaseName = ""; #endif
#else #ifdef _Macintosh const char* kDatabaseName = ":ooftst01:ooftst01.db"; #else const char* kDatabaseName = "ooftst01.db"; #endif const char* kExistsName = kDatabaseName; #endif #endif
Now we open or create the database .
if (dbConnect::fileExists(kExistsName)) {
theDB.openConnection(kDatabaseName);
cout << "Just opened...\n" << theDB << endl << endl;
}
else {
theDB.newConnection(kDatabaseName);
People.AddTestData();
}
We first select all the records and print the database (through a temporary dbView) so we can see its initial state.
People.selectAll(); cout << "Listing records\n" << (dbView(People) << People.LastName << People.OtherNames);
Now we create our searchString array, we just assign some values here, in real life we would probably query the user to enter them, but this way it is much more controlled.
const char* userEntries[] = {"Dent", "Andy"};
Then we call our testing procedures, passing in the array to both, and trying it once as an AND operation and once as an OR operation.
anyName(userEntries, true, numEntries(userEntries)) anyName(userEntries, false, numEntries(userEntries));
Now we create another searchString array and try using the other test procedure.
const char* userEntries2[] = {"Dent", "Tay*"};
lastName(userEntries2, numEntries(userEntries));
cout << "Test Completed" << endl;
return EXIT_SUCCESS; }
This procedure quesries the database, looking for the given substrings within the fields it has governance over (in this case, the two fields LastName and OtherNames).
void anyName(const char* searchStrings[], bool isOr, unsigned short numSch)
{
First we declare our query.
dbQuery theQuery;
Now, depending on what has been pased to this parameter, either all the substrings must be in the search-string (AND) or any combination of the substrings (OR). This next section is just output depending on whether isOr is true or false.
if (isOr) cout << "OR"; else cout << "AND"; cout << " Querying either Last or Othernames = \n";
We query for each string in the list of substrings, so must loop through each like so:
for (unsigned short i=0; i<numSch; i++) {
cout << " " << searchStrings[i] << endl;
We must construct our query clauses on the heap otherwise they are temporaries which won't exist by the time we do the search(). The clauses are assigned the value of the sub-string array??
**************** check this one and explain more fully
dbQueryClause* term1 = new dbQueryBinary( People.LastName == searchStrings[i] ); dbQueryClause* term2 = new dbQueryBinary( People.OtherNames == searchStrings[i] );
The following is a bit subtle - the operator || which takes pointers creates a dbQueryBinaryComboOwner which will delete the sub-clauses
******* don't understand this bit
if (isOr) {
// theQuery |= (*term1 || term2); equivalent to the following
theQuery |= term1;
theQuery |= term2;
}
else
theQuery &= (*term1 || term2);
}
Now we search the database, using the query to be the selection made. We then print the results.
People.search(theQuery);
cout << "\nListing result of query\n" << (dbView(People) << People.LastName << People.OtherNames) << endl;
}
void
lastName(const char* searchStrings[], unsigned short numSch)
{
dbQuery theQuery;
cout << "Querying Lastname = any of\n";
for (unsigned short i=0; i<numSch; i++) {
cout << " " << searchStrings[i] << endl;
// construct clauses on the heap otherwise they are temporaries // which won't exist by the time we do the search()
dbQueryClause* theTerm = new dbQueryBinary( People.LastName == searchStrings[i] );
theQuery |= theTerm; } People.search(theQuery);
cout << "\nListing result of query\n" << (dbView(People) << People.LastName << People.OtherNames) << endl;
}
(c) Copyright A.D. Software 1994-2000 (All Rights Reserved).
Last Updated: 9th September 2001