NOTE: This document is preliminary.
Writing REALbasic Database Plug-Ins
Database plugins are a bit more complex than most other types of REALbasic plug-ins. The database plugin API is described here. All the general plugin comments in the Plugin SDK Documentation apply here as well.
A database plugin may register the following entities:
- Database Engine
- Database Cursor
- Database Source
- Database Source Interface
Required Data Structures
The plugin header files make use of three data structures which are not defined. You must define these as appropriate for your own particular database; RB doesn't care what you put in them. The three structures you
must define are:
- struct dbDatabase
- struct dbTable
- struct dbCursor
Registering a Database Engine
The REALRegisterDBEngine function passes a reference to a REALdbEngineDefinition structure. This is the set of functions which operate primarily on a dbDatabase object, and make up the core of the database functionality.
The fields of the REALdbEngineDefinition structure are as follows:
- version the version of the plugin architecture that the control was built under; just pass the constant kCurrentREALControlVersion
- forSystemUse: just pass 0 (zero)
- flags1:
- flags2:
- flags3:
- closeFunc: pointer to a function with prototype:
closeDB( dbDatabase* database );
- getTableSchemaCursorFunc: pointer to a function with prototype:
REALdbCursor getTableCursor(dbDatabase *database, REALstring tableName, REALgetColumn *columns, REALcolumnConstraints *constraints);
- getFieldSchemaCursorFunc: pointer to a function with prototype:
REALdbCursor getFieldSchema(dbDatabase *database, REALstring tableName);
- directSQLSelectFunc: nil, or a pointer to a function with prototype:
REALdbCursor directSQLSelect(dbDatabase *, REALstring selectString);
- directSQLExecuteFunc: nil, or a pointer to a function with prototype:
void directSQLExecute(dbDatabase *, REALstring executeString);
- createTableFunc: pointer to a function with prototype:
void createTable(dbDatabase *database, REALstring name, REALnewColumn *columns, unsigned char *primaryKey, int primaryKeyCount);
- addTableRecordFunc: pointer to a function with prototype:
void addRecord(dbDatabase *database, REALstring tableName, REALcolumnValue *values);
- getTableCursorFunc: pointer to a function with prototype:
REALdbCursor getTableCursor(dbDatabase *database, REALstring tableName, REALgetColumn *columns, REALcolumnConstraints *constraints);
- updateFieldsFunc: nil, or a pointer to a function with prototype:
void updateFields(dbDatabase *, REALfieldUpdate *fields);
- addTableColumnFunc: nil, or a pointer to a function with prototype:
void addTableColumn(dbDatabase *, REALstring, REALnewColumn *);
- getDatabaseIndexesFunc: pointer to a function with prototype:
REALdbCursor getDatabaseIndexes(dbDatabase *database, REALstring tableName);
- getLastErrorCodeFunc: nil, or a pointer to a function with prototype:
long (*getLastErrorCode)(dbDatabase *);
- getLastErrorStringFunc: nil, or a pointer to a function with prototype:
REALstring getLastErrorString(dbDatabase *);
- commitFunc: pointer to a function with prototype:
void commitTransaction(dbDatabase *database);
- rollbackFunc: pointer to a function with prototype:
void rollbackTransaction(dbDatabase *database);
- getPropertyFunc: nil, or a pointer to a function with prototype:
REALstring getProperty(dbDatabase *database, REALstring propertyName);
Registering a Database Cursor
The REALRegisterDBCursor function passes a reference to a REALdbCursorDefinition structure. This is the set of functions which operate on a database cursor, which is essentially a set of records from a database query. You may register more than one type of cursor, e.g., one for normal queries and one for table schema.
The fields of the REALdbCursorDefinition structure are as follows:
- version the version of the plugin architecture that the control was built under; just pass the constant kCurrentREALControlVersion
- forSystemUse: just pass 0 (zero)
- closeCursorFunc: pointer to a function with prototype:
void closeCursor(dbCursor *);
- cursorColumnCountFunc: pointer to a function with prototype:
int cursorColumnCount(dbCursor *);
- cursorColumnNameFunc: pointer to a function with prototype:
REALstring cursorColumnName(dbCursor *, int column);
- cursorRowCountFunc: nil, or a pointer to a function with prototype:
int cursorRowCount(dbCursor *);
- cursorColumnValueFunc: pointer to a function with prototype:
void cursorColumnValue(dbCursor *, int column, Ptr *outData, dbFieldType *outType, int *outLength);
- cursorReleaseValueFunc: nil, or a pointer to a function with prototype:
void cursorReleaseValue(dbCursor *);
- cursorNextRow: pointer to a function with prototype:
Boolean cursorNextRow(dbCursor *);
- cursorDeleteFunc: nil, or a pointer to a function delete the current record; prototype:
void cursorDelete(dbCursor *);
- cursorDeleteAllFunc: nil, or a pointer to a function to delete all records in the set; prototype:
void cursorDeleteAll(dbCursor *);
- cursorFieldKeyFunc: nil, or a pointer to a mysterious function with prototype:
Boolean cursorFieldKey(dbCursor *, int, Ptr *, int *, Ptr *, int *);
- cursorUpdateFunc: nil, or a pointer to a function with prototype:
void cursorUpdate(dbCursor *cursor, REALcursorUpdate *fields);
- cursorEditFunc: nil, or a pointer to a function with prototype:
void cursorEdit(dbCursor *cursor);
This is called when the RB code does "cursor.Edit".
REALcursorUpdate structure
When the user modifies field values in a cursor, the changes are stored in a REALcursorUpdate struct. This is then passed to your cursorUpdate function. The update data is actually a linked list, defined as:
struct REALcursorUpdate
{
REALcursorUpdate *next;
int fieldIndex;
REALstring columnValue;
};
Your code is responsible for converting the given string data to the appropriate datatype for the backend database.
plugin-doc.html
06 Jun 2000