/*  $Id: object.c,v 1.3 2001/02/21 11:46:46 remlali Exp $
 *
 * Copyright 2000 Larry Liimatainen
 * db_obj.c -- Application database API
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc.,  59 Temple Place - Suite 330, Cambridge, MA 02139, USA.
 *
 *  db_obj.c
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"

#include "tables.h"
#include "ddserver.h"

const char version_of_db_obj[] = "$Id: object.c,v 1.3 2001/02/21 11:46:46 remlali Exp $"; /*usefull to 'strings' the binary*/

extern void debug(); /*this is for gdb*/


/******** Object API **********/

gpointer
db_create_row(gchar *tablename)
{
db_table_descriptor *table;
gpointer row;
gint o, o2;

  table = db_lookup_table(tablename);

  row = g_malloc0 (table->size);

  if( (o = db_lookup_field_offset(table, "created")) == -1 ||
      (o2 = db_lookup_field_offset(table, "modified")) == -1 )
  {
    return row;
  }

  if (row)
    {
      *((guint *) (row + o))  = g_strdup ("(not in database)");
      *((guint *) (row + o2)) = g_strdup ("(not in database)");
      return row;
    }
  return 0;
}


/* db_destroy_row()
*
* tearing down a database record from memory.
* using table descriptors we know alot about
* the record, and tries to free as much as
* possible, rest is left to user.
* Currently we free all fields of String-type.
*
*/

gint db_destroy_row(gchar *tablename, gpointer row)
{
GList *gl;
db_table_descriptor *table;
db_field_descriptor *field;
guint i;

  table = db_lookup_table(tablename);


    gl = table->fields;
    while(gl){
      field = gl->data;
      switch(db_lookup_field_type(table, field->name)){
        case TD_GSTR:
        case TD_PGSTR:
          i = db_lookup_field_offset(table, field->name);
          if(i == -1) return -1;
          g_free( *((gpointer *)(row+i)) );
        break;
        case -1:
          return -1;
      }
      gl = gl->next;
    }
}

/* db_load_table()
*
* This is still a test
* Instead of using hard-coded
* mappings like OBJ_DB_HOST
* definitions to build a filter
* it uses values from
* table configuration file
* to build the filter.
*
* RETURNS: a GList of loaded objects
* on fail: 0
*
*/

GList *
db_load_table(G_sqldb_table *sqldb)
{
db_table_descriptor *table;
db_filter *filter;
db_filter_entry *filent;
GList *gl;
gint i,tpl, n, plen;
gpointer query, tableres;
gchar packet[40000]; /* send-to-daemon buffer */
db_ddr *result;

  filter = sqldb->filter;
  table = db_lookup_table(sqldb->name);

  i = set_pdu_header(packet, TABLE_LOAD_FILTERED, sqldb->name);
  tpl = i;
  if(!filter) goto nofilter;

  gl = filter->entrys;

  while(gl){
    filent = gl->data;
    fprintf(stderr,"Adding filter_field: %s\n", filent->field);
    add_asciiz(&i, packet, filent->field);
    switch(db_lookup_field_type(table, filent->field)){
      case TD_GINT:
      case TD_GUINT:
        fprintf(stderr,"Adding filter_value_int: %u\n", filent->value);
        add_guint(&i, packet, filent->value);
      break;
      case TD_GSTR:
        fprintf(stderr,"Adding filter_value_str: %s\n", filent->value);
        add_asciiz(&i, packet, filent->value);
      break;
      case -1:
        return 0;
    }
    gl = gl->next;
  }

nofilter:

  memcpy(packet+tpl-sizeof(gint), &i, sizeof(gint));        /*write total packet length*/
  result = db_write_read(sqldb->channel, n, &packet);

  if(!result) return FALSE;
  n = sizeof(gint) * 2;

  gl = NULL;
  while((tableres = decode_members(table, result->data, &n, result->len))){
    gl = g_list_append(gl, tableres);
  }
  g_free(result->data);
  g_free(result);
  return gl;
}

/* db_find_rows()
*
* returns a GList of
* object loaded
* using a filter.
*
*/


GList *
db_find_rows(G_sqldb_table *sqldb)
{
  db_filter *filter;
  db_filter_entry *entry;
  db_table_descriptor *table;
  db_field_descriptor *field;
  gpointer row;
  GList *gl, *glr, *glres = NULL;

  guint i,t;

  filter = sqldb->filter;
  table = db_lookup_table(sqldb->name);
  glr = g_sqldb_table_list(sqldb);

  while(glr){
    row = glr->data;
    t = 1;            /* set found-flag to true */
    gl = filter->entrys;
    while(gl){ /* walk through each entry in filter */
      entry = gl->data;
      i = db_lookup_field_offset(table, entry->field);
      if(i == -1) return 0;
      switch(db_lookup_field_type(table, entry->field)){
        case TD_GINT:
        case TD_GUINT:
          if(!( *((gpointer *) entry->value) == *((gpointer *)(row+i)) ))
            t = 0; /* clear found-flag, guint mismatch */
        break;
        case TD_GSTR:
          if(strcmp(entry->value, *((gpointer *)(row+i)) ))
            t = 0; /* clear found-flag string mismatch */
        break;
        case -1:
          return -1;
      }
      gl = gl->next; /* next entry in filter */
    }
    if(t) glres = g_list_append(glres, row);    /* has passed the filter */
    glr = glr->next;                            /* next row in table*/
  }
  return glres;
}

