⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbelement.c

📁 linux下的电话本的最底层
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	librecord2 - Record Object manipulation and storage library 2 * *	Authors: YE Nan <nan.ye@orange-ftgroup.com>  *	 *	This software and associated documentation files (the "Software")  *	are copyright (C) 2005 LiPS Linux Phone Standards Forum [FranceTelecom]  *	All Rights Reserved.  * *	A copyright license is hereby granted for redistribution and use of  *	the Software in source and binary forms, with or without modification,  *	provided that the following conditions are met:  *	- Redistributions of source code must retain the above copyright notice,  *	this copyright license and the following disclaimer.  *  - Redistributions in binary form must reproduce the above copyright  * 	notice, this copyright license and the following disclaimer in the  *	documentation and/or other materials provided with the distribution.  *	- Neither the name of LiPS  nor the names of its Members may be used  *	to endorse or promote products derived from the Software without  *	specific prior written permission.  * *	A patent license for any Necessary Claims owned by Members of LiPS Forum  *	to make, have made, use, import, offer to sell, lease and sell or otherwise  *	distribute any implementation compliant with the any specification adopted  *	by the LiPS Forumcan be obtained from the respective Members on reasonable  *	and non-discriminatory terms and conditions and under reciprocity, as  *	regulated in more detail in the Internal Policy of the LiPS Forum.  * *	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER, ITS MEMBERS AND CONTRIBUTORS  *	"AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,  *	THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE  *	AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER,  *	ITS MEMBERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  *	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  *	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  *	OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  *	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)  *	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  *	POSSIBILITY OF SUCH DAMAGE.  */#include <stdio.h>#include <string.h>#include <glib.h>#include <sqlite3.h>#include <database.h>#include <utils.h>#include "internal.h"#define	FIDSMAP_TABLE_CREATE_TEMPLATE	"CREATE TABLE IF NOT EXISTS %s_fidsmap ( ftid%d %s, ftid INTEGER, def INTEGER, PRIMARY KEY ( ftid%d, ftid ));"#define	FIDSMAP_TABLE_INSERT_TEMPLATE	"INSERT INTO %s_fidsmap ( ftid%d, ftid, def) VALUES ( :001, :002, :003 );"#define	FIDSMAP_TABLE_UPDATE_TEMPLATE	"UPDATE %s_fidsmap SET def = :001 WHERE ( ftid%d = :002 ) & ( ftid = :003);"#define	EXTEND_TABLE_CREATE_TEMPLATE	"CREATE TABLE IF NOT EXISTS %s_ext_%s ( ftid%d %s, fid INTEGER, label TEXT,  desc TEXT, value %s, PRIMARY KEY ( ftid%d, fid ));"#define	EXTEND_TABLE_INSERT_TEMPLATE	"INSERT INTO %s_ext_%s ( ftid%d, fid, label, desc, value ) VALUES ( :001, :002, :003, :004, :005 );"#define	EXTEND_TABLE_UPDATE_TEMPLATE	"UPDATE %s_ext_%s SET label = :001, desc = :002, value = :003 WHERE ( fid = :004 ) & ( ftid%d = :005 );"static char * ftstrs [DB_FIELDS_NTYPES] = {	"INTEGER",	"REAL",	"TEXT",	"BLOB",};static gbooleanrecord_db_element_check_template_validity (RecordDBElement	*element){	Iterator * iter = NULL;	gint count;	g_return_val_if_fail(element, FALSE);	g_return_val_if_fail(element->db_elm_template, FALSE);	iter = field_template_get_ftids(element->db_elm_template);	count = 0;	element->db_elm_id_ftid = FIELD_TEMPLATE_ID_INVALID;	for(iterator_to_first(iter);			!iterator_at_last(iter);			iterator_next(iter))	{		guint32 ftid = *(guint32 *)iterator_current(iter);		const FieldDescriptor *fdesc = NULL;				fdesc = field_template_get(element->db_elm_template,															 ftid);		if (fdesc)		{			/*			 * Check validity of a datebase template, and			 * find out element "ID" field identifier:			 *			 * Validity:			 * 1. One and only one "ID" field(FIELD_ATTR_PRIMARY).			 * 2. "ID" field SHOULD NOT has FIELD_ATTR_MULTI attribute.			 * 3. "ID" field SHOULD be INTEGER (currently).			 */					if (fdesc->attribute & FIELD_ATTR_PRIMARY)			{				if (element->db_elm_id_ftid != FIELD_TEMPLATE_ID_INVALID)				{					g_print("%s(): more than one primary field %d, previous %d.\n",									__FUNCTION__,									ftid,									element->db_elm_id_ftid);					goto failure;				}								if (fdesc->attribute & FIELD_ATTR_MULTIPLE)				{					g_print("%s(): primary field %d CANNOT set MULTI.\n",									__FUNCTION__,									ftid);					goto failure;				}								element->db_elm_id_ftid = fdesc->identifier;				switch (fdesc->type)				{					case FIELD_TYPE_INTEGER:						element->db_elm_id_type = DB_FIELDS_INTEGER;						break;											case FIELD_TYPE_STRING:					case FIELD_TYPE_DATE:					case FIELD_TYPE_BOOLEAN:					case FIELD_TYPE_FLOAT:					default:						g_print("%s(): primary field type SHOULD be INTEGER.\n",										__FUNCTION__);																element->db_elm_id_type = DB_FIELDS_INVALID;						goto failure;						break;				}			}			count++;		}				switch (fdesc->type)		{			case FIELD_TYPE_DATE:			case FIELD_TYPE_BOOLEAN:			case FIELD_TYPE_INTEGER:				DB_FIELDS_TYPES_SET(element->db_elm_field_types,														DB_FIELDS_INTEGER);				break;							case FIELD_TYPE_FLOAT:				DB_FIELDS_TYPES_SET(element->db_elm_field_types,														DB_FIELDS_REAL);				break;							case FIELD_TYPE_STRING:				DB_FIELDS_TYPES_SET(element->db_elm_field_types,														DB_FIELDS_TEXT);				break;			case FIELD_TYPE_BINARY:			default:				DB_FIELDS_TYPES_SET(element->db_elm_field_types,														DB_FIELDS_BLOB);				break;		}	}	iterator_free(iter, TRUE);	g_print("%s(): PRIMARY FTID: %d[%s], types = 0x%08x\n",					__FUNCTION__,					element->db_elm_id_ftid,					ftstrs[element->db_elm_id_type],					element->db_elm_field_types);	return TRUE;failure:	iterator_free(iter, TRUE);	return FALSE;}static gbooleanrecord_db_element_create_tables (RecordDBElement	*element){	Iterator * iter = NULL;	GString * main_sqlstr = NULL;	GString * ext_sqlstr = NULL;	GString * fidsmap_sqlstr = NULL;	GString * columns_str = NULL;	gchar * errmsg = NULL;	gint i;		g_return_val_if_fail(element, FALSE);	columns_str = g_string_new("( ");	/*	 * Create main table of database element.	 * Each field in template exists as a single column(ftid%d)	 * in main table and stores its default value.	 */	iter = field_template_get_ftids(element->db_elm_template);	for (iterator_to_first(iter);			 !iterator_at_last(iter);			 iterator_next(iter))	{		guint32 ftid = *(guint32 *)iterator_current(iter);		const FieldDescriptor *fdesc = NULL;		fdesc = field_template_get(element->db_elm_template,															 ftid);		g_string_append_printf(columns_str,													 "ftid%d ",													 fdesc->identifier);		switch (fdesc->type)		{			case FIELD_TYPE_BINARY:				g_string_append(columns_str, 												ftstrs[DB_FIELDS_BLOB]);				break;			case FIELD_TYPE_INTEGER:			case FIELD_TYPE_DATE:			case FIELD_TYPE_BOOLEAN:				g_string_append(columns_str, 												ftstrs[DB_FIELDS_INTEGER]);				break;			case FIELD_TYPE_FLOAT:				g_string_append(columns_str,												ftstrs[DB_FIELDS_REAL]);				break;			default:				g_string_append(columns_str,												ftstrs[DB_FIELDS_TEXT]);				break;		}		if (fdesc->attribute & FIELD_ATTR_REQUIRED)		{			g_string_append(columns_str, " NOT NULL");		}		g_string_append(columns_str, ", ");	}	iterator_free(iter, TRUE);	main_sqlstr = g_string_new("");	g_string_append_printf(main_sqlstr,												 "CREATE TABLE IF NOT EXISTS %s_main ",												 element->db_elm_name);	g_string_append(main_sqlstr,									columns_str->str);	g_string_append(main_sqlstr,									"extflag INTEGER, ");	g_string_append_printf(main_sqlstr,												 "PRIMARY KEY ( ftid%d ) );",												 element->db_elm_id_ftid);	g_string_free(columns_str, TRUE);/*	g_print("CREATE MAIN TABLE sql:\n%s\n",					main_sqlstr->str);*/		if (record_db_open(element->db) != DB_ERROR_NONE)	{		goto failure;	}	while (record_db_inner_trans_begin(element->db, 																		 DB_TRANS_DEFERRED) != DB_ERROR_NONE);	if (sqlite3_exec(element->db->database,									 main_sqlstr->str,									 NULL,									 NULL,									 &errmsg) != SQLITE_OK)	{		g_print("%s(): create main table failed: %s.\n",						__FUNCTION__,						errmsg);		goto failure;	}	/*	 * Create extend tables for database element.	 * The extended fields is categoried with its 	 * field type. The field with the same field 	 * type will be stored in the same extend table.	 * So the number of extend tables depends on the 	 * number of field type in field templte of current	 * database element.	 */	ext_sqlstr = g_string_new("");	for (i = 0; i < DB_FIELDS_NTYPES; i++)	{/*		g_print("%s(): i = %d, set = %s\n",						__FUNCTION__,						i,						(element->db_elm_field_types & (1 << i) ? "TRUE" : "FALSE"));*/				if (!(element->db_elm_field_types & (1 << i)))		{			continue; 		}				g_string_append_printf(ext_sqlstr,													 EXTEND_TABLE_CREATE_TEMPLATE,													 element->db_elm_name,													 ftstrs[i],													 element->db_elm_id_ftid,													 ftstrs[element->db_elm_id_type],													 ftstrs[i],													 element->db_elm_id_ftid);			/*		g_print("CREATE EXTEND TABLE sql:\n%s\n",						ext_sqlstr->str);*/								if (sqlite3_exec(element->db->database,										 ext_sqlstr->str,										 NULL,										 NULL,										 &errmsg) != SQLITE_OK)		{			g_print("%s(): create extend table failed: %s.\n",							__FUNCTION__,							errmsg);				goto failure;		}				g_string_assign(ext_sqlstr, ""); 	}		/*	 * Create default fid map for echo field template.	 * If deafult field of the field template is changed,	 * there will be one row newly created to describe this. 	 */	fidsmap_sqlstr = g_string_new("");	g_string_append_printf(fidsmap_sqlstr,												 FIDSMAP_TABLE_CREATE_TEMPLATE,												 element->db_elm_name,												 element->db_elm_id_ftid,												 ftstrs[element->db_elm_id_type],												 element->db_elm_id_ftid);			/*	g_print("CREATE FIDSMAP sql:\n%s\n",					fidsmap_sqlstr->str);*/	if (sqlite3_exec(element->db->database,									 fidsmap_sqlstr->str,									 NULL,									 NULL,									 &errmsg) != SQLITE_OK)	{		g_print("%s(): create fidsmap table failed: %s.\n",						__FUNCTION__,						errmsg);		goto failure;	}		record_db_inner_trans_commit(element->db);	record_db_close(element->db);	g_string_free(main_sqlstr, TRUE);	g_string_free(ext_sqlstr, TRUE);	g_string_free(fidsmap_sqlstr, TRUE);	return TRUE;failure:	record_db_close(element->db);		g_string_free(main_sqlstr, TRUE);	g_string_free(ext_sqlstr, TRUE);	g_string_free(fidsmap_sqlstr, TRUE);	g_free(errmsg);	return FALSE;}void record_db_element_print (const RecordDBElement	*element){	g_return_if_fail(element);		g_print("RecordDBElement: [0x%08x]\n",					(guint32)element);	g_print("|- Name           : %s\n",					(guint32)element->db_elm_name);	g_print("|- RecordDB       : 0x%08x\n",					(guint32)element->db);	g_print("|- Template       : 0x%08x\n",					(guint32)element->db_elm_template);	g_print("|- Field Types    : 0x%08x\n",					element->db_elm_field_types);	g_print("|- Primary FTID   : %d\n",					element->db_elm_id_ftid);	g_print("`- Primary Type   : 0x%08x\n",					element->db_elm_id_type);		return;}/** * @brief		Create a #RecordDBElement object, initialized with * 					the given information. * * @param		db				database object handler * @param		name			element name * @param		template	field template used for element  * * @return	newly-created #RecordDBElement object or NULL if failed. */RecordDBElement *record_db_element_new (RecordDB							*db,											 const gchar					*name,											 const FieldTemplate	*template){	RecordDBElement *element = NULL;	g_return_val_if_fail(db, NULL);	g_return_val_if_fail(name, NULL);	g_return_val_if_fail(template, NULL);	element = g_new0(RecordDBElement, 1);	if (element == NULL)	{		return NULL;	}	element->db										= db;	element->db_elm_name					= g_strdup(name);	element->db_elm_template			= template;	element->db_elm_field_types		= 0x0;	element->db_elm_id_ftid				= FIELD_TEMPLATE_ID_INVALID;	element->db_elm_id_type				= DB_FIELDS_TEXT;	if (g_hash_table_lookup(db->elements, 													(gpointer)name) == NULL)	{		gchar * key = NULL;				key = g_strdup(name);		g_hash_table_replace(db->elements, 												 (gpointer)key,												 (gpointer)element);	}	else	{		g_print("%s(): %s element already exists.\n",						__FUNCTION__,						element);		record_db_element_free(element);		return NULL;	}	if (record_db_element_check_template_validity(element) == FALSE)	{		g_print("%s(): check validity failed.\n",						__FUNCTION__);		record_db_element_free(element);		return NULL;	}	if (record_db_element_create_tables(element) == FALSE)	{		g_print("%s(): create table failed.\n",						__FUNCTION__);		record_db_element_free(element);		return NULL;	}		return element;}/** * @brief		Frees the memory allocated for the #RecordDBElement object. * * @param		element		the #RecordDBElement object */voidrecord_db_element_free (RecordDBElement	*element){	g_return_if_fail(element);		g_hash_table_remove(element->db->elements,											(gpointer)element->db_elm_name);		g_free(element->db_elm_name);	g_free(element);	return;}static voidbind_value_by_fid (sqlite3_stmt		*pStmt,									 guint32				 fid,									 gconstpointer	 value,									 gint						 type,									 gint						 size){	gchar * name = NULL;	gint index  = 0;	/*	 * use fid to fill pattern ":%03d" to location the	 * colum binding in a SQLite statement binary codes.	 */	name = sqlite3_mprintf(":%03d", fid);	index = sqlite3_bind_parameter_index(pStmt, name);	sqlite3_free(name);//	g_print("%s(): fid = %d, type = %d, size = %d\n", __FUNCTION__, fid, type, size);	switch (type)	{		case FIELD_TYPE_STRING://			g_print("%s(): value = %s\n", __FUNCTION__, value);			sqlite3_bind_text(pStmt,												index,												(gchar *)value,												strlen((gchar *)value),												SQLITE_TRANSIENT);			break;		/*		 * INTEGER field SHOULD NOT treated as 		 * binary or it will lead a logical error		 * when database manipulations.		 */		case FIELD_TYPE_INTEGER:			sqlite3_bind_int(pStmt,											 index,											 *(gint *)value);			break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -