UDA 注册表
在使用任何注册表功能之前,应用程序必须为元字典结构分配空间,并使用 mco_metadict_init() API 初始化分配的缓冲区。由于应用程序可能使用多个数据库,因此元字典必须包含每个数据库字典的头和条目。缓冲区的大小应通过 mco_metadict_size() 函数获取,该函数返回元字典的大小(以字节为单位,包括头)。
void mco_metadict_size( unsigned short n_entries, unsigned int * size );
typedef struct tag_mco_metadict_header_t_
{
unsigned short n_maxentries; /* The maximum number of database
* dictonaries*/
unsigned short n_allocated; /* The current number of registered
* dictionaries */
} mco_metadict_header_t;
typedef struct tag_mco_metadict_entry_t_
{
unsigned short dict_no; /* dictionary number (starting with 0) */
unsigned short flags; /* internal flag */
char name[16]; /* dictionary name */
void * dict; /* internal pointer */
void * user_data; /* application data */
} mco_metadict_entry_t;现在,可以调用 mco_metadict_init() 函数来初始化元字典。在调用任何 UDA API 函数之前,必须先调用此函数。
MCO_RET mco_metadict_init (
mco_metadict_header_t * metadict,
unsigned int size,
unsigned int flags
);应用程序需要分配内存缓冲区,并将缓冲区指针及其大小传递给 mco_metadict_init() 函数。数据库运行时将确定元字典中可注册的最大数据库数量。应用程序可以通过 metadict->n_maxentries 字段访问此数量。
请注意,mcouda 库不会分配任何动态内存。因此,UDA API 使用的任何内存缓冲区都由应用程序分配。缓冲区可以静态声明,也可以在堆上分配。描述符通常在应用程序的栈上分配。
当在常规内存(而非共享内存)中创建数据库时,运行时会自动将所有已打开的数据库在元字典中进行注册(记录)。元字典中的字典名称被指定为数据库名称。
flags 参数定义了字典初始化期间的行为。目前唯一支持的值为:
MCO_METADICT_DONT_LOAD_EXISTING_DBS此标志表明未自动注册打开的数据库。 以下 API 函数将数据库字典注册到元字典中:
MCO_RET mco_metadict_register (
mco_metadict_header_t * metadict,
const char * name,
const void * dict,
const void * user_data
);请注意,mco_metadict_init() 会自动注册已打开的常规内存数据库。如果在元字典初始化之后才打开数据库,则可以使用 mco_metadict_register() API 进行注册。可以在打开数据库之前或不打开数据库的情况下注册数据库字典(例如,应用程序可能只需要接收特定的模式(字典)信息)。
还可以使用以下 API 自动将当前数据库连接的数据库字典注册到元字典中:
MCO_RET mco_metadict_register_conn(
mco_metadict_header_t * metadict,
const mco_db_h connection,
const void * user_data
);与函数 mco_metadict_register() 不同,此函数不需要指向由 mcocomp 生成的字典结构的指针。因此,对于数据库字典最初未知的应用程序来说,它是理想的选择,例如当应用程序打开由另一个应用程序在共享内存中创建的数据库时。
函数 mco_metadict_register_conn() 的另一个用例是使用诸如创建表、修改表等 SQL 动态 DDL 操作的应用程序。由于数据库表是通过 SQL DDL 操作创建或修改的,因此无法使用任何静态定义的数据访问函数;即由 mcocomp 生成的函数。但可以在元字典中注册这样的字典,然后使用 UDA API 访问其数据。当然,每次修改字典时都需要重新注册。每当 SQL 操作更改数据库模式时,函数 mco_trans_start() 都会返回错误代码 MCO_E_SCHEMA_CHANGED。在这种情况下,应关闭当前连接,然后重新连接;然后使用新获得的连接将其字典注册到元字典中。
为了在元词典中注销未使用的词典条目,提供了以下函数:
MCO_RET mco_metadict_unregister(
mco_metadict_header_t * metadict,
const char *name
);此函数将指定的字典条目标记为空。在元字典注册之后,可以调用以下 API 函数来获取已注册数据库的数量:
MCO_RET mco_metadict_count (
const mco_metadict_header_t * metadict,
/* out */ unsigned short * count
);由于可以从元字典中注销字典,所以在查询字典数组时必须考虑到这一点。因此,保持在元字典中注册的字典条目的原始顺序非常重要。出于这个原因,函数 mco_metadict_unregister() 只是将字典条目标记为空。函数 mco_metadict_count() 返回元字典中已分配条目的总数。如果使用了字典注销操作,则需要检查函数 mco_metadict_entry() 返回的值,该值指示具有指定编号的字典是否实际存在。例如,以下代码片段演示了如何实现对元字典中条目的循环:
/* Get total number of registered dictionaries and print out info for each */
mco_metadict_count(metadict, &count);
for (dict_no = 0; dict_no < count; ++dict_no)
{
MCO_RET rc;
mco_metadict_entry_t *entry;
/* Get dictionary by number and check if it is registered */
rc = mco_metadict_entry(metadict, dict_no, &entry);
if (MCO_E_UDA_DICT_NOTFOUND == rc)
continue;
/* Process metadictionary entry */
...
}请注意,代码行 if (rc == MCO_E_UDA_NOTFOUND) continue; 会跳过之前未注册的字典条目。 有 API 函数可以根据字典的编号、名称或连接句柄获取指向字典的指针:
MCO_RET mco_metadict_entry( const mco_metadict_header_t * metadict,
unsigned short dict_no,
/* out */ mco_metadict_entry_t ** entry );
MCO_RET mco_metadict_entry_name( const mco_metadict_header_t * metadict,
const char * name,
/* out */ mco_metadict_entry_t ** entry );
MCO_RET mco_metadict_entry_conn( const mco_metadict_header_t * metadict,
const mco_db_h connection,
/* OUT */ mco_metadict_entry_t ** entry );可以通过以下方式获取数据库字典中结构/类的数量:
MCO_RET mco_dict_struct_count(
const mco_metadict_header_t * metadict,
unsigned short dict_no,
/* out */ unsigned short * count
);通过以下方式获取基于其编号或名称的结构体/类的指针:
MCO_RET mco_dict_struct(
const mco_metadict_header_t * metadict,
unsigned short dict_no,
unsigned short struct_no,
/* out */ mco_dict_struct_info_p struct_info
);
MCO_RET mco_dict_struct_name(
const mco_metadict_header_t * metadict,
unsigned short dict_no,
const char * name,
/* out */ mco_dict_struct_info_p struct_info
);