Once the user performs a successful database connect, the database handle can be used to operate on the tables that are part of that database.
Every time a new table is created, or an existing table is added to a database, some of the table properties such as table name, path, data file extension, index file extension, etc, are placed in an entry of the database dictionary file (a per-database file that FairCom DB uses to keep track of each database).
Every time a user activates a table by opening it with ctdbOpenTable(), the handle of that table is placed in a list of active (connected) tables within the database handle. When a table is deactivated, or closed by calling ctdbCloseTable(), the table handle is removed from the list of active tables in the database handle. A user may query the active table list by locating the first active table, the next active table, or a specific active table.
Some specific steps must be taken when creating a new table using the FairCom DB API API:
The code fragment below creates a new table, with two fields and no indexes. Please note that error checking was omitted:
/* allocate a new table handle */
hTable = ctdbAllocTable(hDatabase);
/* add a field
ctdbAddField(hTable, "Field0", CT_INTEGER, 4);
/* add another field */
ctdbAddField(hTable, "Field1", CT_CHAR, 30);
/* create the table */
ctdbCreateTable(hTable, "MyTable", CTCREATE_NORMAL);
Working with Tables describes the process of creating a table in detail.
You can add an extra level of data integrity when creating a new table by placing the code to create a table inside a transaction. If the transaction is aborted, the table entry in the database dictionary file is removed, and the table data and index files are deleted from disk.
When a table is created inside a transaction, and until the transaction is committed or aborted, the newly created table must be opened with CTOPEN_EXCLUSIVE mode, otherwise the table open operation will fail. After the transaction is committed the table can be opened in non-exclusive mode.
The code fragment below creates a new table under transaction control. Again no error checking code is included in the example:
/* allocate a new table handle and associate it with a database */
hTable = ctdbAllocTable(hDatabase);
/* begin a transaction */
ctdbBegin(hTable);
/* add a field
ctdbAddField(hTable, "Field0", CT_INTEGER, 4);
/* add another field */
ctdbAddField(hTable, "Field1", CT_CHAR, 30);
/* create the table in the associated database */
ctdbCreateTable(hTable, "MyTable", CTCREATE_NORMAL);
/* commit the transaction */
ctdbCommit(hTable);
An existing table may be added or imported to a database by calling ctdbAddTable(). ctdbAddTable() takes a database handle, the table name, and the path where the database is located.
/* add MyTable to the current database */
if (ctdbAddTable(hDatabase, "MyTable", "") != CTDBRET_OK)
printf("Add table failed\n");
An extra level of data integrity may be achieved when you add an existing table to a database under transaction control. When the transaction is committed the database dictionary data for the table is committed to disk. If the transaction is aborted, the dictionary data for the table is automatically removed from the database dictionary.
The code fragment below shows how to add an existing table under transaction control. No error checking is included in the sample code:
/* begin a transaction */
ctdbBegin(hDatabase);
/* add MyTable to the current database */
if (ctdbAddTable(hDatabase, "MyTable", "") != CTDBRET_OK) {
printf("Add table failed\n");
ctdbAbort(hDatabase);
} else {
printf("Add table\n");
ctdbCommit(hDatabase);
}
When you drop a table from a database, the table information is removed from the database dictionary, but the table data and index files are left untouched. The drop table operation can be reversed with an add table operation. Drop a table from a database by calling ctdbDropTable().
/* drop MyTable from current database */
if (ctdbDropTable(hDatabase, "MyTable") != CTDBRET_OK)
printf("Drop table failed\n");
An extra level of data integrity may be achieved when you drop a table from a database under transaction control. When the transaction is committed the changes to the database dictionary data for the table is committed to disk. If the transaction is aborted, the dictionary data for the table is automatically restored to the database dictionary.
The code fragment below shows how to drop an existing table under transaction control. No error checking is included in the sample code:
/* start a transaction */
ctdbBegin(hDatabase);
/* drop MyTable from current database */
if (ctdbDropTable(hDatabase, "MyTable") != CTDBRET_OK) {
printf("Drop table failed\n");
ctdbAbort(hDatabase);
} else {
printf("Drop table\n");
ctdbCommit(hDatabase);
}
When you delete a table from a database, the table information is removed from the database dictionary and the table data and index files are deleted from disk. The delete table operation can be reversed only when used under transaction control (by using the roll back functionality – see the ctrdmp utility). Without transaction control, a delete table operation will permanently delete the data and index files and the table data will be lost. Delete a table from a database by calling ctdbDeleteTable().
/* delete MyTable from current database */
if (ctdbDeleteTable(hDatabase, "MyTable", NULL) != CTDBRET_OK)
printf("Delete table failed\n");
ctdbDeleteTable() takes as parameters a database handle, the table name, and the table password. Set the password parameter to NULL if a table was created without a password. Note that active/open tables must be closed before they can be deleted.
Note: ctdbDeleteTable() is for use within a CTDB session. For a CTREE session, you must use ctdbRemoveTable(). See also Allocating a Session Handle.
An extra level of data integrity may be achieved when you delete a table from a database under transaction control. When the transaction is committed the changes to the database dictionary data for the table is committed to disk and the table and index files are permanently deleted from disk. If the transaction is aborted, the dictionary data for the table is automatically restored to the database dictionary and the original data and index files are restored to their original state.
The code fragment below shows how to delete an existing table under transaction control. No error checking is included in the sample code:
/* start a transaction */
ctdbBegin(hDatabase);
/* delete MyTable from current database */
if (ctdbDeleteTable(hDatabase, "MyTable", NULL) != CTDBRET_OK) {
printf("Delete table failed\n");
ctdbAbort(hDatabase);
} else {
printf("Delete table\n");
ctdbCommit(hDatabase);
}
ctdbFirstTable() retrieves the name and path of the first table in a database dictionary. If the database has no tables, ctdbFirstTable() returns INOT_ERR (101). See the example in Next Table.
ctdbNextTable() retrieves the name and path of the next table in a database or returns INOT_ERR (101) when the last table in the current database dictionary has already been retrieved.
/* Display all tables in a database */
CTDBRET DisplayTables(CTHANDLE hDatabase)
{
CTDBRET Retval;
TEXT Name[MAX_NAME];
TEXT Path[MAX_PATH];
if ((Retval = ctdbFirstTable(hDatabase,Name,sizeof(Name),
Path,sizeof(Path)) == CTDBRET_OK)
{
do {
printf("Table: %s Database: %s\n", Name, Path);
Retval = ctdbNextTable(hDatabase, Name, sizeof(Name),
Path, sizeof(Path);
} while (Retval == CTDBRET_OK);
}
if (Retval == INOT_ERR) {
Retval = CTDBRET_OK;
}
return Retval;
}
ctdbFindTable() retrieves the path of a specific table in a database dictionary given the table name. If the table is not in the dictionary, ctdbFindTable() returns INOT_ERR (101).
/* return YES if table exist or NO if table does not exit */
CTBOOL TableExist(CTHANDLE hDatabase, pTEXT tblName)
{
TEXT tblPath[MAX_NAME];
return(ctdbFindTable(hDatabase,TblName,tblPath,sizeof(tblPath))
== CTDBRET_OK) ? YES : NO;
}
ctdbGetFirstActiveTable() retrieves the table handle of the first active/open table in a database dictionary. If the database dictionary contains no active/open tables, ctdbGetFirstActiveTable() returns NULL.
ctdbGetNextActiveTable() retrieves the table handle of the next active/open table in a database dictionary. After the handle of the last active/open table in that database dictionary has been retrieved, ctdbGetNextActiveTable() returns NULL.
/* Display all active tables */
void DisplayActiveTables(CTHANDLE hDatabase)
{
VRLEN hScan;
CTHANDLE hTable;
if ((hTable = ctdbGetFirstActiveTable(hDatabase, &hScan)) != NULL) {
do {
printf("Table: %s Path: %s\n",ctdbGetTableName(hTable),ctdbGetTablePath(hTable));
hTable = ctdbGetNextActiveTable(hDatabase, &hScan);
} while (hTable != NULL);
}
}
ctdbFindActiveTable() retrieves the handle of a specific active/open table in the database dictionary. If that table is not active/connected, or it is not in the database dictionary, ctdbFindActiveTable() returns NULL.
/* Check if table is active */
CTBOOL IsTableActive(CTHANDLE hDatabase, pTEXT tblName)
{
return (ctdbFindActiveTable(hDatabase, tblName) != NULL) ? YES : NO;
}
The function above is shown for example purposes only. ctdbIsActiveTable() provides a more efficient way to check if a table is active.
When a table is created or added to a database, an automatic and unique identifier (UID) is associated with the table. A table UID is unique within the database associated with the table.
A table UID is an unsigned long value that can be used as an alternative method to operate on tables, once the table is created or added to a database.
ctdbFindTableByUID() retrieves the name and path of a table in a database dictionary given the table UID. ctdbFindTableByUID() requires a database or a table handle. The following example shows how to implement a table open function using the table UID instead of the table name.
/* open table using UID */
CTDBRET OpenByUID(CTHANDLE hTable, ULONG uid, CTOPEN_MODE OpenMode)
{
TEXT tblName[MAX_NAME];
TEXT tblPath[MAX_PATH];
CTDBRET Retval;
Retval = ctdbFindTableByUID(hTable, uid, tblName, sizeof(dbName),
tblPath, sizeof(tblPath));
if (Retval == CTDBRET_OK)
Retval = ctdbOpenTable(hTable, tblName, OpenMode);
return Retval;
}
The code fragment above is provided as example only. ctdbOpenTableByUID() will open a table using the table UID.
ctdbFindActiveTableByUID() retrieves the handle of an active/open table in a database dictionary given the table's UID. The following example shows how to check if a table is active using its UID:
/* check if a table is active, by UID */
CTBOOL IsActiveTableByUID(CTHANDLE hTable, ULONG uid)
{
return (ctdbFindActiveTableByUID(hTable, uid) != NULL) ? YES : NO;
}