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

📄 dbobject.c

📁 bonddb 是一个源于PostgreSQL封装包的对象。它是一个由C/C++编写的快速数据提取层应用软件
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <glib.h>#include "db.h"#include "dbobject.h"#include "debug.h"#include "dbwrapper.h"#include "dbgather.h"#include "dbconstraint.h"#include "dbmapme.h"#include "dbsqlparse.h"#include "dbobjectvalid.h"#include "dbbureaucrat.h"#include "dbtoliet.h"#include "dbuniqueid.h"#include "dbobjectnav.h"#include "dbfield.h"#include "dbbirth.h"#include "dbcache.h"/* Not part of hte main db_API.  But a side function   If a record is new, and hasn't been in database then this function   will go and blonk it into the database *//* Write ahead cache   flush out all writes to db and free cache. 	This function has been re-written way to much and is such a fundemental one to the whole	project. Recode with caution, many a dead programme scatter this lines of code.... . *//** * db_obj_addwrite: * @obj: database object * @field: fieldname to write to * @value: value to write to that field * @mark: whether or not to leave a mark on the object that you wrote.  Set to TRUE normally. * * For the given @obj add a write to the @field at the current row the object is on.  The record * must have a table name supplied to it on creation in order to write back.  This is a low level * function, you should generally use db_setvalue().  Also note this wont write back straight away but * at some time when it thinks it appropriate.  The @mark is for things like default values where you * want to save a value but you want to wait till you get some real data before writing back and this is just * one of those optional extra values to have. * * Returns: non-zero on failure. */gintdb_obj_addwrite(Object * obj, gchar * field, gchar * table, gchar * value, gboolean mark)	{	DbCache *cache;	g_assert(obj);	g_assert(field);	if (value != NULL && strlen(value) == 0)		value = NULL;	/* debugmsg("Write to cache of %s.%s of value %s", obj->name, field, value); */	cache = db_cache_isincache(obj);	if (cache == NULL)		{		/* This is the first write to this object so create a cache for it. */		cache = db_cache_moveto(obj);		/* m.essage("%s.%s: Adding writeid of %d",obj->name,field,obj->id->pg_oid); */		/* State the object is new, or edited or whatever */		if (db_id_isnewrecord(obj->id) == TRUE)			cache->state = OBJ_NEW;		else			cache->state = OBJ_EDITREAD;		}	/* hmm mark. If its set to mark it then mark it. */	if (mark == TRUE)		{		/* record that you did some write... so if you have an object previously in cache you dump it. */		db_bureaucrat_recordwrite(obj->objectinstance);		/* debugmsg("Marking object %s with a write", obj->name); */		obj->changed = TRUE;		cache->changed = TRUE;		}	/* now we actually going to do it.. */	db_cache_setvalue(obj, cache, field, table, value);	return 0;	}/** * db_obj_doread: * @obj: Database object * @field: name of field to read * @value: value to return * * This shoulnd't be called directly, but what it does is check to see if a value is in cache, * and when and if its not then it will read it from the database.  This is done on your currently * selected row in the database, use db_moveto() to navigate the recordset.  Don't free @value when * your done. * * Returns: non-zero on failure */gintdb_obj_doread(Object * obj, gchar * field, gchar * table, gchar ** value)	{	gint retval, fieldpos;	DbCache *cache;	DbField *fielddef;	g_assert(obj);	g_assert(field);	*value = NULL;	/* check cache */	cache = db_cache_isincache(obj);	/* db_obj_debug(obj); */	/* check if we have the record cached */	if (cache != NULL)		{		/* m.essage("checking in cache. hmm. row is %d, orig row is %d", obj->row, cache->origrow); */		/* Read the item from the cache */		retval = db_cache_getvalue(obj, cache, field, table, value);		/* m.essage("returning value. hmm. %d, %s", retval, *value); */		if (*value == NULL)			{			/* If the record is in fact blank, return that as the value */			if (cache->state == OBJ_NEW || cache->state == OBJ_EDITNEW)				return retval;			/* Continue on with reading from the record set to load the cache */			}		else			{			/* Its a function, run the function to get the value */			if (strcmp(*value, "EXECFUNCTION") == 0)				{				debugmsg("This is a default value field (%s) you are getting the value from", field);				fielddef = db_field_dbfind(obj, field, table);				if (fielddef->fielddef->defaultvalue != NULL)					{					*value = db_default_execfunction(fielddef->fielddef->defaultvalue);					db_cache_setvalue(obj, cache, field, table, *value);					mem_free(*value);					db_cache_getvalue(obj, cache, field, table, value);					}				debugmsg("returning %s for default value", *value);				}			return retval;			}		}	/* no data in there */	if (db_isnewrecord(obj) == TRUE)		{		*value = NULL;		return 1;		}	/* do a normal read */	retval = db_field_read(obj, field, table, value);	/* m.essage("read %s from %s.%s",value,table,field); */	/* if your in a filtered object, then save everything you read to cache */	if (cache == NULL && obj->filtered == TRUE)		cache = db_cache_moveto(obj);	if (cache != NULL)		{		/* assumes the state is defaulted to a OBJ_NEW */		if (cache->state == OBJ_NEW)			cache->state = OBJ_READ;		if (obj->filtered == TRUE)			if ((fieldpos = db_cache_setvalue(obj, cache, field, table, *value)) >= 0)				* value = cache->value[fieldpos];		}	return retval;	}/** * db_obj_sqlread: * * Awaiting documentation patrol. * * Returns: Salvation */gintdb_obj_sqlread(Object * obj, gchar * sql)	{	g_assert(obj);	g_assert(sql);	if (db_bureaucrat_checkpendingwrites(obj) > 0)		debugmsg("had to write some stuff before i could run this sql.");	/* run query */	obj->query = db_id_verifysql(sql);	if (obj->query == NULL)		{		errormsg("Failed to modify SQL statement to include keys, %s", sql);		return -2;		}	obj->res = db_dbexec(globaldbconn, obj->query);	debugmsg("%s", obj->query);	/* check for errors */	if (db_dbcheckresult(obj->res) != 0)		{		errormsg("error in running query %s", obj->query);		obj->res = NULL;		return -1;		}	/* check number of records loaded, as well as record number loaded */	obj->res->basetable = db_sqlparse_getfirsttable(obj->query);	/* obj->name = obj->res->basetable; */	if ((obj->num = db_dbnumrows(obj->res)) <= 0)		{		/* This needs to be relooked at so that an empty object is created when you have zero results */		debugmsg("No records found for loading %s", obj->query);		if (obj->name == NULL)			{			obj->name = db_sqlparse_getfirsttable(obj->query);			debugmsg("I'm assuming table name of %s, and hoping for the best", obj->name);			}		/* db_obj_clear(obj); */		if (obj->res != NULL)			{			/*			if (obj->freeresult == TRUE) */			db_dbclear(obj->res);			obj->res = NULL;			}		db_obj_handle_empty_recordset(obj);		/* g_assert(obj->name); */		return 1;		}	/* get number of fields */	/* this was the old way, now replaced by populate */	/* num = db_dbnumfields(obj->res); obj->numfield = num; */	/* Assign record defaults to a read, data unchanged */	obj->newrecord = FALSE;	obj->freeresult = TRUE;	obj->changed = FALSE;	obj->unknownid = FALSE;	obj->filtered = FALSE;	/* I suspect this code is buggy so i'm putting a reminder that I need to get a hair cut because i'll visit here	   often */	obj->readonly = FALSE;	/* populate that object, Yeaaah! */	db_field_populate(obj);	db_moveto(obj, 0);	/* Run some tests */	if (db_isnewrecord(obj) == TRUE)		g_assert(NULL);	return 0;	}/** * db_obj_sqlwrite: * @query: An insert or update query string * @targettable: The table your running the query on * @id: If its an insert then you want to record the new id for the object. * * Execture a insert or a update, this is used in internally by the flushing. * You shoulnd't need to call this function. * * Returns: negitive on failure, 1 on insert, 0 on update. */gintdb_obj_sqlwrite(gchar * query, gchar * targettable, DbUniqueId ** id)	{	gint retval = 0;	DbRecordSet *res;	g_assert(query);	*id = NULL;	/* execute the write query */	debugmsg("%s", query);	res = db_dbexec(globaldbconn, query);	res->basetable = mem_strdup(targettable);	/* check result */	if (db_checkpgresult(res) != 0)		{		errormsg("%s Query Failed", query);		/* clean up the odd ends for the object */		return -1;		}	/* If you ran an insert re-get the uniqueid and record it in the cache for future reference. */	if ((*id = db_uniqueid(res)) != NULL)		retval = 1;	db_dbclear(res);	return retval;	}/** * db_obj_test: * @obj: Database object * * Run a series of tests on an object to make sure it is not courpt. * * Returns: non-zero on failure. */gintdb_obj_test(Object * obj)	{	gint f = 0, i;	/* Disabled to improve speed */	return 0;	if (obj == NULL)		errormsg("%d, object is null", f++);	if (obj->name == NULL)		errormsg("%d,object can not be written back to db.", f++);	/*   if (obj->res == NULL && obj->query != NULL)	      errormsg("%d,object has no recordset", f++); */	if (obj->id == NULL)		errormsg("%d,id is null", f++);	if (obj->row < 0)		errormsg("%d,row is invalid", f++);	if (obj->cache == NULL && obj->changed == TRUE)		warningmsg("%d,cache is null, but the object has changed", f++);	for (i = 0; i < obj->numcache; i++)		{		if (obj->cache[i]->origrow == obj->row)			if (db_id_compare(obj->cache[i]->id, obj->id) != 0)				errormsg("%d, cache is courpt.", f++);		}	f += db_field_test(obj);	return (0 - f);	}/** * db_obj_create: * @name: Optional name of a table * * Creates a blank empty object which can then used for reading or writing into.  This is  * internal code. * * Returns: Newly created database object */Object *db_obj_create(gchar * tablename)	{	Object *obj;	obj = (Object *) mem_alloc(sizeof(Object));	memset(obj, 0, sizeof(Object));	obj->objectinstance = -1;	if (tablename == NULL)		{		obj->readonly = TRUE;		obj->name = NULL;		}	else		{		obj->readonly = FALSE;		obj->name = mem_strdup(tablename);		}	obj->res = NULL;	obj->row = 0;	obj->num = 1;	obj->numfield = 0;	obj->freeresult = FALSE;	obj->newrecord = TRUE;	obj->unknownid = TRUE;	obj->changed = FALSE;	obj->filtered = FALSE;	obj->sqlgood = TRUE;	obj->fulldbsupport = TRUE;	obj->query = NULL;

⌨️ 快捷键说明

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