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

📄 dbbirth.c

📁 bonddb 是一个源于PostgreSQL封装包的对象。它是一个由C/C++编写的快速数据提取层应用软件
💻 C
字号:
#include <glib.h>#include "db.h"#include "dbbirth.h"#include "dbobject.h"#include "debug.h"#include "dbfield.h"#include "dbconstraint.h"#include "dbgather.h"#include "dbtoliet.h"#include "dbsqlparse.h"/** Oh i'm sooo screwed *//** * db_birth_addvalue: * @birth: Birth to assign the value to * @field: field in the birth statement, that was in the original sql statement * @value: value to assign * * Add a value into a birth structure.   * * Returns: non-zero on failure */gintdb_birth_addvalue(DbBirth * birth, gchar * fieldname, gchar * value)   {   gint fieldpos;   g_assert(birth);   g_assert(fieldname);   g_assert(value);   fieldpos = db_field_arraypos(birth->field, birth->num, fieldname);   if (fieldpos < 0)      {      errormsg("I was unable to find the field %s in the table %s", fieldname, birth->tablename);      errormsg("Invalid field position %d, hmmm. I'm looking for %s", fieldpos, fieldname);      return -1;      }   /* free up some old data */   if (birth->value[fieldpos] != NULL)      mem_free(birth->value[fieldpos]);   /* add the value */   if (value != NULL)      birth->value[fieldpos] = mem_strdup(value);   else      birth->value[fieldpos] = NULL;   /* mark this field as essential */   birth->essential[fieldpos] = 1;	/*debugmsg("Added %s to %s (%s)",value,fieldname,birth->value[fieldpos]);*/   return 0;   }/** * db_birth_createsql: * @birth: previsouly created birth describing relationship * * Generate the sql statement needed to create the desired object set.  Using the values * set in the birth this will create an sql select statement from the tablename. * SELECT * FROM birth->tableame WHERE birth.field.name = birth.value ... * * Returns: %NULL on error else a valid birth. */gchar *db_birth_createsql(DbBirth * birth)   {   gchar *retstr, *tables, *endbit;   gchar **query = NULL, **tablenames = NULL;   gint i, j, found, numtables = 0, numwhere = 0;   g_assert(birth);   /* checks to see if is a simple query */   if (birth->num < 1)      {      retstr = mem_strdup_printf("SELECT * FROM %s", birth->tablename);      return retstr;      }   query = (gchar **) mem_alloc(sizeof(gchar *) * (birth->num + 1));   /* parse 1, get number of tables */   for (i = 0; i < birth->num; i++)      {      /* dont added it to the sql if you dont need it */      if (birth->value[i] == NULL)         continue;      found = 0;      for (j = 0; j < numtables; j++)         {         if (strcmp(birth->field[i]->table, tablenames[j]) == 0)            found = 1;         }      if (found == 0)         {         tablenames = (gchar **) mem_realloc(tablenames, sizeof(gchar *) * (numtables + 3));         tablenames[numtables] = mem_strdup(birth->field[i]->table);         numtables++;         }      }   /* parse 2, construct where statements */   for (i = 0; i < birth->num; i++)      {      /* dont added it to the sql if you dont need it */      if (birth->value[i] == NULL)         continue;      if (numtables > 1)         query[numwhere++] =            mem_strdup_printf("%s.%s='%s'", birth->field[i]->table, birth->field[i]->field, birth->value[i]);      else         query[numwhere++] = mem_strdup_printf("%s='%s'", birth->field[i]->field, birth->value[i]);      }   if (numtables == 0)      {      warningmsg("Nothing here to run so i'm aborting");      return NULL;      }   tablenames[numtables] = NULL;   query[numwhere] = NULL;   tables = g_strjoinv(",", tablenames);   endbit = g_strjoinv(" AND ", query);   retstr = mem_strdup_printf("SELECT * FROM %s WHERE %s", tables, endbit);   for (i = 0; i < numtables; i++)      mem_free(tablenames[i]);   g_free(tables);   g_free(endbit);   mem_free(tablenames);   for (i = 0; i < numwhere; i++)      mem_free(query[i]);	   mem_free(query);   return retstr;   }/** * db_birth_createfromsql: * @sql: sql SELECT query string * * Given a sql select statement, create a birth object defining how it was created * * Returns: DbBirth object */DbBirth *db_birth_createfromsql(gchar * sql)   {   DbBirth *birth = NULL;	DbField **fields;	gchar **value;	gint num, i;   birth = (DbBirth *) mem_alloc(sizeof(DbBirth));	memset(birth,0,sizeof(DbBirth));   birth->sql = mem_strdup(sql);   birth->essential = NULL;   birth->tablename = db_sqlparse_getfirsttable(sql);   birth->num = db_field_numfieldbytable(birth->tablename);   birth->field = mem_calloc(sizeof(DbField*)*(birth->num+1));   birth->value = mem_calloc(sizeof(gchar*)*(birth->num+1));   birth->essential = mem_calloc(sizeof(gchar*)*(birth->num+1));   for (i = 0; i < birth->num; i++)		{		birth->field[i] = db_field_getbytable(birth->tablename, i);		birth->value[i] = NULL;		}mem_checkboundaries();	/* put items into the object */   birth->id = NULL;	   num = db_sqlparse_getwherefieldsandvalues(sql, &fields, &value);	if (fields!=NULL && value != NULL)		{		for (i=0;i<num;i++)			{			db_birth_addvalue(birth, fields[i]->field, value[i]);			db_field_free(fields[i]);			mem_free(value[i]);			}		mem_free(fields);		mem_free(value);		}   return birth;   }/** * db_birth_create: * @id: Unique id or %NULL if your not looking at loading a specific record * @tablename: Name of table you wish to create birth for. * * Will create a DbBirth structure, which you can then call other functions on like  * db_birth_addvalue(). * * Returns: Newly created DbBirth contains details on how to create an object. */DbBirth *db_birth_create(DbUniqueId * id, gchar * tablename)   {   gint i;   DbBirth *birth;   g_assert(tablename);   birth = (DbBirth *) mem_alloc(sizeof(DbBirth));	memset(birth,0,sizeof(DbBirth));   birth->sql = NULL;   birth->value = NULL;   birth->field = NULL;   birth->essential = NULL;   birth->tablename = tablename;   birth->num = 0;   birth->id = id;   /* get out if this is still null */   if (tablename == NULL)      return birth;   /* continue with allocation then */   birth->num = db_field_numfieldbytable(tablename);   birth->field = (DbField **) mem_alloc(sizeof(DbField *) * birth->num);   birth->value = (gchar **) mem_alloc(sizeof(gchar *) * birth->num);   birth->essential = (gchar *) mem_alloc(sizeof(gchar) * birth->num);   for (i = 0; i < birth->num; i++)      {      birth->value[i] = NULL;      birth->essential[i] = 0;      birth->field[i] = db_field_getbytable(tablename, i);      }   return birth;   }/** * db_birth_free: * * need to document here me feels */voiddb_birth_free(DbBirth * birth)   {   gint i;    if (birth == NULL)      return ;   /* free up birth values */   for (i = 0; i < birth->num; i++)      {      if (birth->value[i] != NULL)         mem_free(birth->value[i]);      db_field_free(birth->field[i]);      }   if (birth->essential != NULL)      mem_free(birth->essential);   if (birth->value != NULL)      mem_free(birth->value);   if (birth->field != NULL)      mem_free(birth->field);   if (birth->sql != NULL)      mem_free(birth->sql);   mem_free(birth);   }/** * db_birth_applycref: * @obj: database object source, which is used to generate new birth.  This is the source object * @birth: previously allocated by db_birth_createsql() * @cref: database constrant reference which defines the relationship between @obj and @birth * * Modify the dbbirth with db_birth_addvalue() to make it able to create an object based on the * cref. This is used for functions like db_loadobjectbyobject(). * * Returns: non-zero on failure */gintdb_birth_applycref(Object * obj, DbBirth * birth, DbConstraintDef * cref)   {   gint retval;   gchar *localvalue = NULL, *destfield = NULL;   gchar *localfield = NULL, *localtable = NULL;   g_assert(obj);   g_assert(birth);   g_assert(cref);   if (strcmp(cref->table[0], obj->name) == 0)      {      localtable = cref->table[0];      localfield = cref->column[0];      destfield = cref->column[1];      }   else if (strcmp(cref->table[1], obj->name) == 0)      {      localtable = cref->table[1];      localfield = cref->column[1];      destfield = cref->column[0];      }   else      {      errormsg("Invalid CREF. aborting here");      return -1;      }   if (db_getvalue(obj, localfield, localtable, &localvalue) != 0)      {      errormsg("unable to read desired values");      return -2;      }	/*debugmsg("readinng %s from %s.",localvalue,localfield);*/   if (localvalue == NULL)      {      debugmsg("problem occured in extracting desired value");      return -3;      }	   retval = db_birth_addvalue(birth, destfield, localvalue);   return retval;   }/** * db_birth_save: * @obj: database object to put the birth into * @birth: previously allocated by db_birth_createsql() which describes how @obj was created *  * Record how @obj was created by placing the @birth into the data structure.  This is needed * in order to handle data refreshes and working out when values change in one object, when * to update other objects. * * Returns: non-zero on failure */gintdb_birth_save(Object * obj, DbBirth * birth)   {   g_assert(obj);   g_assert(birth);   if (obj->birth != NULL)      db_birth_free(obj->birth);   obj->birth = birth;   g_assert(birth);   return 0;   }/** * db_birth_springchicken: * @obj Spring Chicken * @birth: Birth Mark * * Apply the birth mark to the spring chicken. * * Returns: non-zero on chicken rejecting birth mark */gintdb_birth_springchicken(Object * obj)   {   gint i;   DbBirth *birth;   g_assert(obj);   birth = obj->birth;   if (birth == NULL)      {      errormsg("birth is null. highly invalid here");      db_obj_test(obj);      db_obj_debug(obj);      return -1;      }	if (birth->value == NULL && birth->num > 0)		{		errormsg("Invalid birth structure");		return -1;		}   for (i = 0; i < birth->num; i++)      if (birth->value[i] && birth->essential[i] == 1)         {         /* m.essage("adding value %s to field %s",birth->value[i],birth->field[i]->field); */         db_setvalue_nomark(obj, birth->field[i]->field, NULL, birth->value[i]);         }   return 0;   }/* ======================================================================================= * And now for something completely different... * ======================================================================================= */static GList *db_birth_gettablelist(Object * obj)   {   GList *retlist = NULL;   gint i;   for (i = 0; i < obj->numfield; i++)      {      if (retlist != NULL)         {         if (g_list_find(retlist, obj->field[i]->table) == NULL)            retlist = g_list_append(retlist, obj->field[i]->table);         }      else         retlist = g_list_append(retlist, obj->field[i]->table);      }   return retlist;   }static gbooleandb_birth_istableinside(Object * obj, GList * tablelist)   {   GList *walk, *othertable, *elem;   othertable = db_birth_gettablelist(obj);   for (walk = g_list_first(tablelist); walk != NULL; walk = walk->next)      {      elem = g_list_find(othertable, walk->data);      if (elem != NULL)         {         g_list_free(othertable);         return TRUE;         }      }   g_list_free(othertable);   return FALSE;   }static gbooleandb_birth_fieldcompare(DbField * field1, DbField * field2)   {   g_assert(field1);   g_assert(field2);   if (strcmp(field1->field, field2->field) == 0 && strcmp(field2->table, field2->table) == 0)      return TRUE;   return FALSE;   }/** * db_birth_iseffected: * @objcheck: database object - object to check if the cache effects it, its the one contains the birth * @objchanged: database object - object that contains the cache. * @cache: write element to compare it against. * * Strange drunkcard coding... * Check to see if the @objcheck contains parts of @objchanged. * * Check to see if the @cache write will effect this object in any way, and if so, do * some writes to the object so it gets those values instead of the ones still sitting * in its recordset. This offically stops you from needing to re-run your queries in order * to have uptodate data. * * Returns: 1 on effected, 0 on not effected, negitive on error */gbooleandb_birth_iseffected(Object * objcheck, Object * objchanged, DbCache * cache)   {   gint i, j, count = 0, topass = 0;   GList *tablelist;   DbBirth *birth;   /* this is one hell function that required much vokda inorder to write, and or       understand.  If you struggle with it please help yourself to a drink. */   if (objchanged->numfield != cache->num)      {      errormsg("Problem, cache->num != objchanged->num. This is on checking %s against %s", objcheck->name,               objchanged->name);      warningmsg("cache->num:%d != objchanged->num:%d", cache->num, objchanged->num);      db_obj_debug(objchanged);      }   /* get a list of tables this touchs */   tablelist = db_birth_gettablelist(objcheck);   /* see if a table occurs inside objchanged */   if (db_birth_istableinside(objchanged, tablelist) == TRUE)      {      birth = objcheck->birth;      /* if your working on the same id then of course they are effected. */      if (birth->id != NULL)         {         if (db_id_compare(birth->id, cache->id) == TRUE)            return TRUE;         }      /* check all the requirements for the objectcheck */      for (i = 0; i < birth->num; i++)         {         if (birth->value[i] != NULL)            {            topass++;            /* go though cache and see if it meets the specifications. */            for (j = 0; j < cache->num; j++)               {               if (cache->value[j] != NULL)                  /* check the conditions to make sure that ... I ENDED UP SOMEHWERE ELSE */                  if (strcmp(cache->value[j], birth->value[i]) == 0)                     if ((db_birth_fieldcompare(objchanged->field[j], birth->field[i]) == TRUE))                        count++;               }            }         }      if (count == topass)         return TRUE;      }   return FALSE;   }

⌨️ 快捷键说明

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