Part I: Surfing through databases
One of the amazing capabilities of the Palm OS is its embedded database support. The DB Manager API allows fulfilling different operations to be done easily and effectively. Unlike Windows CE, where basic DB operations may totally confuse an unexperienced programmer, here you need to know just the database’s name to start. In this article, we will try to highlight how to handle some basic operations with Palm OS databases.
To be more practical, let’s develop a simple DB explorer. The application will give full access to manage any file on the handheld. In other words, it should copy, move, and delete databases and also show/edit their parameters.
The first thing the application will do is to enumerate all existing databases and show them in a list. For this purpose, the Palm OS API has several functions:
- DmNumDatabases,
- DmGetDatabase,
- DmDatabaseInfo.
You can get the total number of installed databases (including applications, which are just a special type of database) with the DmNumDatabases function. You can then loop over them, getting each by a DmGetDatabase call and finally getting DB info with DmDatabaseInfo. The following code example illustrates how to do it:
static Err AppStart(void) { UInt16 nDBCount = DmNumDatabases(0); LocalID liDB = 0; char szDBName[33]; UInt32 creator = 0; g_nCurrIdx = 0; if ( nDBCount ) { g_pszListChoices = (Char**) new Char*[nDBCount]; g_arrCreators = (UInt32*) new UInt32[nDBCount]; } for (UInt16 i = 0; i < nDBCount; i++) { liDB = DmGetDatabase(0,i); if ( liDB ) { Err err = DmDatabaseInfo(0,liDB,szDBName,0,0,0,0,0,0,0,0,0, &creator); if ( err == errNone ) { g_pszListChoices[g_nCurrIdx] = (Char*)new Char[sizeof( szDBName)]; MemSet(g_pszListChoices[g_nCurrIdx],sizeof(szDBName),0); MemMove(g_pszListChoices[g_nCurrIdx],szDBName,StrLen( szDBName)); g_arrCreators[g_nCurrIdx] = creator; g_nCurrIdx++; } } } return errNone; }
As you see, the above database in Palm OS may be described by two parameters: the memory card number and local ID. Cards are numbered, starting with 0 for the internal card. If you don’t use some external memory, specify 0 as the card number. Local ID is just an offset from the beginning of the memory card where database is located, so it’s unique value for each database. After the DB card number and local ID are specified , you are ready to get different information about the selected DB. Just take a look at the function declaration:
Err DmDatabaseInfo(UInt16 cardNo, LocalID dbID, Char *nameP, UInt16 *attributesP, UInt16 *versionP, UInt32 *crDateP, UInt32 *modDateP, UInt32 *bckUpDateP, UInt32 *modNumP, LocalID *appInfoIDP, LocalID *sortInfoIDP, UInt32 *typeP, UInt32 *creatorP) SYS_TRAP(sysTrapDmDatabaseInfo);
All parameters except cardNo and dbID are output; in other words, that’s the info being requested. As you see above, you may also get the local ID of the application and sort info blocks. It is useful for you as an application developer when you need to store some additional data (such as program-specific settings) into your database. Similarly, if you want to save a reference to a memory block within a record, you should convert its handle (valid only when the application is running) to the corresponding local ID and store it. In the browser, only the database name, creator, and version will be shown.
Okay, databases are enumerated, so the DB info may be retrieved as well as set up by using the DmSetDatabaseInfo function with analogues parameters. Due to the fact that the application is just a browser, it will use only DmDatabaseInfo to display database parameters and DmDatabaseSize to get the database size and number of records. Note that database type and creator are 4-byte integers that are normally represented as a 4-character sequence. Any combination is allowed, but
totally lowercase creators are reserved.
The following example illustrates how to fetch the database size and number of records:
LocalID liDB = DmFindDatabase(0,szDBName); UInt32 nRecords,nTotalBytes; DmDatabaseSize(0, liDB, &nRecords, &nTotalBytes, 0);
You can see the result in this picture. And finally, let’s show the database attributes on a separate screen.
Note that we still have not opened any database, but have gotten a lot of useful information.
Conclusions
Even though the Data and Resource Manager APIs are pretty rich (and here we have used a tiny part of it), a you have a simple and straightforward way to obtain desired information about the content of a Palm device. Such a technique may be convenient when the application uses many different databases or needs to interact with ‘external’ programs. But again, this is just a small drop in the Palm OS sea…
About the Author
Alex Gusev started to play with mainframes in the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a head of the Mobile R department, making programmers’ lives in the mobile jungles a little bit simpler.
# # #