Compact 2013 Ebook

18.2 CEDB
Created by djones on 7/29/2013 4:52:06 PM

CEDB

Given that Windows CE evolved from Personal Organizers (CE 1), there have been native database technologies from day one to support such things as Address Books. These database engines, whilst supporting such things as queries to sort and search, were only simple technologies hosting simple data. For example, CEDB databases have no schema and so when a record is stored, the data in a field can be of any type.

Compact 7 had two lower level database engine, CEDB and EDB. CEDB is used by low level things by the kernel including object store. EDB was a requirement of any GUI based OS and was required by higher level things such as CAB installer, Media Player, SQL Compact, Pocket Outlook, MAPI and ActiveSync. Given that these are no longer the need for EDB have been obviated. Only CEDB is available in Compact 2013.

CEDB can stores databases as files. They can be in RAM, in the Object Store, the internal file system as well as external storage such a flash. In the following example a CEDB is created in Object Store.

1.     A native code application is required to exercise the CEDB API. Create a C++ Console as a subproject of the OS.

2.     Add the following code above  WinMain( ) function in the project’s .cpp file in the order listed:

#define NUMFIELDS  2

#define NUMRECORDWRITES  4

#define RECORDTOSEEK 2

#define DATABASE_TYPE  137

#define MYDB  "MyDB"

Listing 18.1 Application parameters
The parameters for the application define the database name and type as well as some parameters for how the application will run (e.g. the number of records created.

 

void ErrorMessages (DWORD err)

{

RETAILMSG(1,( _T("Error %d "),err));

if (err = ERROR_SHARING_VIOLATION) RETAILMSG(1,(
_T("ERROR_SHARING_VIOLATION: Indicates that the file is in use.")));

else if (err = ERROR_INVALID_PARAMETER) RETAILMSG(1,(
_T("ERROR_INVALID_PARAMETER: Indicates that a parameter was invalid.")));

 

// … And more of these. See Help for error messages each of the CEDB API functions

}

Listing 18.2 Error message handler

This a shortened version of the error handler. It takes a value returned from GetLastError( ) by the calling code and generates an appropriate message. The macros and strings are in the function documentation on MSDN. With each of the API calls, if the return value is a correct value then a success message is written to the Debug window. If it is incorrect then it gets the error number and calls this function.

3.     Add the following code in the WinMain( ) function in the project’s .cpp file in the order listed:

RETAILMSG(1,( _T("Starting CEDBApp ")));

 

//Create a CEDB in the Object Store

RETAILMSG(1,( _T("Creating DB")));

 

CEOID MyCEOID =  CeCreateDatabase(

   _T(MYDB),   //DB Name

   DATABASE_TYPE,  //User Defined

   0,              //Number of s0rt orders. Use default

   NULL            //Array of sort orders

);

 

if (MyCEOID)

{

   RETAILMSG(1,( _T("Created DB")));

   RETAILMSG(1,( _T("CEOD for DB = %d "), MyCEOID ));

}

else

{

   RETAILMSG(1,( _T("Creation Failed")));

   ErrorMessages(GetLastError());

}

 

Listing 18.3 Create the database

The database creation requires a name, a user defined type (numeric), and default sort order specifications. No sort specifications are used in the above example. The database type can be used in searches. The creation function returns a CEOID which permanently identifies the database.

 

 

///Object Store GUID //////////////////////////////////

RETAILMSG(1,( _T("Get Object Store GUID")));

 

PCEGUID   ObjStoreDBGUID;

try

{

   //Get a System GUID for the Object Store

   //So do it "manually". Object store is a zero GUID.

   ObjStoreDBGUID = (PCEGUID ) LocalAlloc(0,sizeof(CEGUID ));

   ObjStoreDBGUID->Data1=0;

   ObjStoreDBGUID->Data2=0;

   ObjStoreDBGUID->Data3=0;

   ObjStoreDBGUID->Data4=0;

}

   catch (char * str)

{

   RETAILMSG(1,( _T("Exception %s "),str));

}

/// Got GUID /////////////////////////////////////////

 

 

 

RETAILMSG(1,( _T("Got Object Store GUID")));

RETAILMSG(1,( _T("Object Store GUID %d-%d-%d-%d "),
ObjStoreDBGUID->Data1,ObjStoreDBGUID->Data2,
ObjStoreDBGUID->Data3,ObjStoreDBGUID->Data4 ));

 

Listing 18.4 Get Object Store GUID

The Object Store GUID is a “zero” GUID , i.e. all tuples are zero. The
 CREATE_SYSTEMGUID(ObjStoreDBGUID)
 could be used but it was found to be a bit flakey, generating Access Violation some time. The code above is functionally the same as the macro.

 

RETAILMSG(1,( _T("Opening DB")));

SetLastError(0);

HANDLE hndl = CeOpenDatabaseEx2(

   ObjStoreDBGUID,     //Object Store GUID

   &MyCEOID,           //O means use name. But would need to not be just opened

   _T(MYDB),           //Database name. Ignored with 0 as above

   NULL,               //Sort order not important

   CEDB_AUTOINCREMENT, //Auto incr record ptr when reading

   NULL                //Sort order not important

);

 

if (hndl == (HANDLE)-1  )

{

   RETAILMSG(1,( _T("DB NOT Opened")));

   ErrorMessages(GetLastError());

}

else

{

RETAILMSG(1,( _T("DB Opened HANDL= %d"),hndl));

}

 

//If Open failed then don’t do write, read and close, but still delete db

Listing 18.5 Open the database

The database open requires a GUID for the volume on which it is to be created (in this case Object Store), a database CEOID, specification of sort order (none here), and some flags (auto increment the record pointer in this case). The database name could also be used to open the database, by setting the second parameter to zero. This would be used when reopening the database.

//Write Records

DWORD numFields = NUMFIELDS;

 

//Set up record

PCEPROPVAL rgPropVal = (PCEPROPVAL)LocalAlloc ( 0,numFields * sizeof(CEPROPVAL));

CEOID oidRecord = (CEOID) 0; ////New record

 

//Set up data for record, as two fields (two properties)

CEVALUNION  val;

 

val.lpwstr = _T("Hi there!");

rgPropVal[1].val= val;

rgPropVal[1].wLenData = sizeof(DWORD); //Actually not used

rgPropVal[1].wFlags = 0; //No flags

rgPropVal[1].propid = CEVT_LPWSTR; //Val data type

 

CEVALUNION  val2;

val2.iVal= 137;

rgPropVal[0].val= val2; //This will be index later

rgPropVal[0].wLenData = sizeof(DWORD); //Actually not used

rgPropVal[0].wFlags = 0; //No flags

rgPropVal[0].propid = CEVT_I4;

 

RETAILMSG(1,( _T("Writing record to DB")));

 

SetLastError(0);

 

 

for (int i=0; i< i++)>

 

   //Write i into record

   val2.iVal= i; //Set index

   rgPropVal[0].val= val2;

 

 

CEOID WriteRecordGUID =  CeWriteRecordProps(

          hndl,

          oidRecord,

          numFields,

          rgPropVal

);

 

   if (WriteRecordGUID)

RETAILMSG(1,(

_T("Wrote Record CEOID= %d Index= %d"), WriteRecordGUID, rgPropVal[0].val.iVal));

   else

   {

          RETAILMSG(1,( _T("Write Failed")));

          ErrorMessages(GetLastError());

   }

}

free(rgPropVal); //Freed rgPropVal

Listing 18.6 Write Records

 

 

 

//Seek record  (0 based index)

DWORD Index=139;

DWORD dwValue= RECORDTOSEEK;

SetLastError(0);

 

CEOID SeekCEOID = CeSeekDatabaseEx(

   hndl  ,

   CEDB_SEEK_BEGINNING,

   dwValue,

   0,  //Ignored for CEDB_SEEK_BEGINNING

   (LPDWORD) &Index

);

 

 

if (SeekCEOID)

RETAILMSG(1,(
 _T("SEEK CEOID = %d Index found = %d Index sought = %d"),SeekCEOID, Index, dwValue));

else

{

   RETAILMSG(1,( _T("Seek failed")));

   ErrorMessages(GetLastError());

}

 

        Listing 18.7 Seek nth record from start

The SEEK function in this instance requires the open handle for the database a specification of where to seek from and how much to see. CEDB_SEEK_BEGINNING means seek from the beginning, dwValue number of records. There are other search option such as searching from the current record pointer and searching based upon record contents.

 

//Read record

DWORD dwFlags= CEDB_ALLOWREALLOC;

 

WORD numProps = 2;

LPWORD lpcPropID=  &numProps;

 

CEPROPID* rgPropID=NULL;

 

PBYTE  pBuff = 0;

LPBYTE* lplpBuffer  = (LPBYTE*)&pBuff;//(LPBYTE*) LocalAlloc (0,100);;

  

 

DWORD pcBuffer = 0;

LPDWORD lpcbBuffer  =(LPDWORD) &pcBuffer; ;

 

RETAILMSG(1,( _T("Reading Record")));

SetLastError(0);

 

CEOID ReadRecordGUID = CeReadRecordPropsEx(

   hndl,

   CEDB_ALLOWREALLOC,

   lpcPropID,

   NULL,

   ,

   //&(LPBYTE) pBuff,

   lpcbBuffer,

   0  //Use LocalHeap

);

 

if (ReadRecordGUID)

{

   DWORD numFields = NUMFIELDS;

   RETAILMSG(1,(

_T("Read Record CEOID+ %d Num Fields = %d"), ReadRecordGUID, *lpcPropID));

   if (*lpcPropID == numFields) //We only wrote two fields per record

   {

          //Lets write them

          PCEPROPVAL pRecord = (PCEPROPVAL) pBuff;

          RETAILMSG(1,( _T("SUCCESS: Index = %d"),(pRecord+0)->val.iVal));                    

          RETAILMSG(1,( _T("SUCCESS: String = %s"),(pRecord+1)->val.lpwstr));

}

else

{

                

RETAILMSG(1,(
_T("Error: Got %d fields, expected %d"), *lpcPropID,numFields));

}

free(pBuff);

//Don't forget this. It was created on heap by CeReadRecordPropsEx

}

else

{

   RETAILMSG(1,( _T("Read failed")));

   ErrorMessages(GetLastError());

free(pBuff);
//Don't forget this. It may be created on heap by CeReadRecordPropsEx, even if error

}

 

Listing 18.8 Read database record

 

 

 

//Close the database

RETAILMSG(1,( _T("Closing DB")));

SetLastError(0);

BOOL res = CloseHandle(hndl);

if (res)

   RETAILMSG(1,( _T("DB Closed")));

else

{

   RETAILMSG(1,( _T("DB Close failed.")));

   ErrorMessages(GetLastError()); //Need messages

}

 

Listing 18.9 Close the database

The database is closed as per closing a file. Note it would fail if the database was not open.

 

 

//Delete the database

SetLastError(0);

BOOL res =  CeDeleteDatabaseEx(

   ObjStoreDBGUID,

   MyCEOID

);

 

if (res)

   RETAILMSG(1,( _T("DB Deleted")));

else

{

   RETAILMSG(1,( _T("DB Not Deleted")));

   ErrorMessages(GetLastError()); //Need messages

}

free(ObjStoreDBGUID);

return 0;

 

Listing 18.10 Delete the database

The database is specified by its volume store (object Store) GUID and its CEOID.  These are sufficient information to delete the database. Note need to release memory allocated to the Object Store GUID pointer

4.     Build and test run the application. A sample output is shown in Listing 18.11

 

 

1965484 PID:400002 TID:14500b6 RELFSD: Opening file cedbapp.exe from desktop

1965495 PID:1be00de TID:14500b6 Starting CEDBApp

1965495 PID:1be00de TID:14500b6 Creating DB

1965495 PID:1be00de TID:14500b6 Created DB

1965495 PID:1be00de TID:14500b6 CEOD for DB = 838860801

1965495 PID:1be00de TID:14500b6 Get Object Store GUID

1965495 PID:1be00de TID:14500b6 Got Object Store GUID

1965495 PID:1be00de TID:14500b6 Object Store GUID 0-0-0-0

1965495 PID:1be00de TID:14500b6 Opening DB

1965495 PID:1be00de TID:14500b6 DB Opened HANDL= 7682307

1965495 PID:1be00de TID:14500b6 Writing records to DB

1965495 PID:1be00de TID:14500b6 Wrote Record CEOID= 838860803 Index= 0

1965495 PID:1be00de TID:14500b6 Wrote Record CEOID= 838860804 Index= 1

1965495 PID:1be00de TID:14500b6 Wrote Record CEOID= 838860805 Index= 2

1965495 PID:1be00de TID:14500b6 Wrote Record CEOID= 838860806 Index= 3

1965495 PID:1be00de TID:14500b6 SEEK CEOID = 838860805 Index found = 2 Index sought= 2

1965495 PID:1be00de TID:14500b6 Reading Record

1965495 PID:1be00de TID:14500b6 Read Record CEOID= 838860805 Num Fields = 2

1965497 PID:1be00de TID:14500b6 SUCCESS: Index = 2

1965497 PID:1be00de TID:14500b6 SUCCESS: String = Hi there!

1965497 PID:1be00de TID:14500b6 Closing DB

1965497 PID:1be00de TID:14500b6 DB Closed

1965497 PID:1be00de TID:14500b6 DB Deleted

Listing 18.11 CEDBApp Output

 

Note that there is a a bit of a "fudge" in the above. If the code is run twice, then the correct index is returned once, not twice. In the following listing, the seek is set to the first record and then the seven records are read in succession.  Note the slightly disjointed order of the indexes.

 

Run Programs s CEDBApp

 434902 PID:400002 TID:1fa007a RELFSD: Opening file CEDBApp.exe from desktop

 434914 PID:1be0056 TID:1fa007a Starting CEDBApp

 434914 PID:1be0056 TID:1fa007a Creating DB

 434914 PID:1be0056 TID:1fa007a Created DB

 434914 PID:1be0056 TID:1fa007a CEOD for DB = 922746881

 434914 PID:1be0056 TID:1fa007a Get Object Store GUID

 434914 PID:1be0056 TID:1fa007a Got Object Store GUID

 434914 PID:1be0056 TID:1fa007a Object Store GUID 0-0-0-0

 434915 PID:1be0056 TID:1fa007a Openning DB

 434915 PID:1be0056 TID:1fa007a DB Openned HANDL= 7675395

 434915 PID:1be0056 TID:1fa007a Writing record to DB

 434915 PID:1be0056 TID:1fa007a Wrote Record CEOID= 922746885 Index= 0

 434915 PID:1be0056 TID:1fa007a Wrote Record CEOID= 922746884 Index= 1

 434915 PID:1be0056 TID:1fa007a Wrote Record CEOID= 922746883 Index= 2

 434915 PID:1be0056 TID:1fa007a Wrote Record CEOID= 922746882 Index= 3

 434915 PID:1be0056 TID:1fa007a Wrote Record CEOID= 805306375 Index= 4

 434915 PID:1be0056 TID:1fa007a Wrote Record CEOID= 805306376 Index= 5

 434915 PID:1be0056 TID:1fa007a Wrote Record CEOID= 805306377 Index= 6

 434915 PID:1be0056 TID:1fa007a SEEK CEOID = 922746882 Index found= 0 Index sought = 0

 434915 PID:1be0056 TID:1fa007a Reading Record

 434915 PID:1be0056 TID:1fa007a Read Record CEOID+ 922746882 Num Fields = 2

 434916 PID:1be0056 TID:1fa007a SUCCESS: Index = 3

 434916 PID:1be0056 TID:1fa007a SUCCESS: String = Hi there!

 434916 PID:1be0056 TID:1fa007a Reading Record

 434916 PID:1be0056 TID:1fa007a Read Record CEOID+ 922746883 Num Fields = 2

 434916 PID:1be0056 TID:1fa007a SUCCESS: Index = 2

 434916 PID:1be0056 TID:1fa007a SUCCESS: String = Hi there!

 434916 PID:1be0056 TID:1fa007a Reading Record

 434924 PID:1be0056 TID:1fa007a Read Record CEOID+ 922746884 Num Fields = 2

 434924 PID:1be0056 TID:1fa007a SUCCESS: Index = 1

 434924 PID:1be0056 TID:1fa007a SUCCESS: String = Hi there!

  434924 PID:1be0056 TID:1fa007a Reading Record

 434924 PID:1be0056 TID:1fa007a Read Record CEOID+ 922746885 Num Fields = 2

 434924 PID:1be0056 TID:1fa007a SUCCESS: Index = 0

 434924 PID:1be0056 TID:1fa007a SUCCESS: String = Hi there!

  434924 PID:1be0056 TID:1fa007a Reading Record

 434924 PID:1be0056 TID:1fa007a Read Record CEOID+ 805306375 Num Fields = 2

 434925 PID:1be0056 TID:1fa007a SUCCESS: Index = 4

 434925 PID:1be0056 TID:1fa007a SUCCESS: String = Hi there!

  434931 PID:1be0056 TID:1fa007a Reading Record

 434931 PID:1be0056 TID:1fa007a Read Record CEOID+ 805306376 Num Fields = 2

 434931 PID:1be0056 TID:1fa007a SUCCESS: Index = 5

 434931 PID:1be0056 TID:1fa007a SUCCESS: String = Hi there!

 434931 PID:1be0056 TID:1fa007a Reading Record

 434931 PID:1be0056 TID:1fa007a Read Record CEOID+ 805306377 Num Fields = 2

 434932 PID:1be0056 TID:1fa007a SUCCESS: Index = 6

 434932 PID:1be0056 TID:1fa007a SUCCESS: String = Hi there!

 434932 PID:1be0056 TID:1fa007a Closing DB

 434932 PID:1be0056 TID:1fa007a DB Closed

 434932 PID:1be0056 TID:1fa007a DB Deleted

 

The reason is because when the database was set up no sort order was defined and hence the seek and selects are jumbled. A sort order could be defined to resolve this, or all of the records could be returned as above, then sorted in software.


NEXT:  SQLite

print

Click here to provide feedback and input

  Comments


Turkish porno izle video site in rokettubeporno izle