/*++++++++++++++++++++
risdata.c: defines an object to pool RIS data before passing them to a db
markus@mhoenicka.de 2003-10-01

   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, see <http://www.gnu.org/licenses/>

   +++++++++++++++++++++++++*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <dbi/dbi.h>

#include "refdb.h"
#include "linklist.h"
#include "refdbd.h"
#include "risdata.h"
#include "strfncs.h"

extern int n_log_level;


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  new_risdata(): creates a new risdata object

  struct RISDATA* new_risdata returns a ptr to the new object or NULL
                  if we're out of memory

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
struct RISDATA* new_risdata(void) {
  struct RISDATA* ptr_risdata;

  if ((ptr_risdata = malloc(sizeof(struct RISDATA))) == NULL) {
    return NULL;
  }
  else {
    reset_risdata(ptr_risdata);
    return ptr_risdata;
  }
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  free_risdata(): frees the memory allocated by a risdata object
                  it is safe to call this function with a NULL ptr

  void free_risdata returns nothing

  struct RISDATA* ptr_risdata ptr to a risdata object

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void free_risdata(struct RISDATA* ptr_risdata) {
  if (!ptr_risdata) {
    return;
  }

  if (ptr_risdata->abstract) {
    free(ptr_risdata->abstract);
  }

  if (ptr_risdata->title_series) {
    free(ptr_risdata->title_series);
  }

  if (ptr_risdata->booktitle) {
    free(ptr_risdata->booktitle);
  }

  if (ptr_risdata->title) {
    free(ptr_risdata->title);
  }

  if (ptr_risdata->address) {
    free(ptr_risdata->address);
  }

  free(ptr_risdata);
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  reset_risdata(): resets the strings and ptrs of a risdata object

  void reset_risdata returns nothing

  struct RISDATA* ptr_risdata ptr to a risdata object

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void reset_risdata(struct RISDATA* ptr_risdata) {
  if (!ptr_risdata) {
    return;
  }

  ptr_risdata->n_id = 0;
  ptr_risdata->n_pubyear = 0;
  ptr_risdata->n_secyear = 0;
  *(ptr_risdata->pyother_info) = '\0';
  *(ptr_risdata->secother_info) = '\0';
  *(ptr_risdata->citekey) = '\0';
  *(ptr_risdata->user1) = '\0';
  *(ptr_risdata->user2) = '\0';
  *(ptr_risdata->user3) = '\0';
  *(ptr_risdata->user4) = '\0';
  *(ptr_risdata->user5) = '\0';
  *(ptr_risdata->typeofwork) = '\0';
  *(ptr_risdata->area) = '\0';
  *(ptr_risdata->ostype) = '\0';
  *(ptr_risdata->degree) = '\0';
  *(ptr_risdata->runningtime) = '\0';
  *(ptr_risdata->classcodeintl) = '\0';
  *(ptr_risdata->classcodeus) = '\0';
  *(ptr_risdata->senderemail) = '\0';
  *(ptr_risdata->recipientemail) = '\0';
  *(ptr_risdata->mediatype) = '\0';
  *(ptr_risdata->numvolumes) = '\0';
  *(ptr_risdata->edition) = '\0';
  *(ptr_risdata->computer) = '\0';
  *(ptr_risdata->conferencelocation) = '\0';
  *(ptr_risdata->registrynum) = '\0';
  *(ptr_risdata->classification) = '\0';
  *(ptr_risdata->section) = '\0';
  *(ptr_risdata->pamphletnum) = '\0';
  *(ptr_risdata->chapternum) = '\0';
  *(ptr_risdata->issn) = '\0';
  *(ptr_risdata->issue) = '\0';
  *(ptr_risdata->publisher) = '\0';
  *(ptr_risdata->city) = '\0';
  *(ptr_risdata->volume) = '\0';
  *(ptr_risdata->endpage) = '\0';
  *(ptr_risdata->startpage) = '\0';
  strcpy(ptr_risdata->type, "\'GEN\'"); /* use GEN as a default */
  ptr_risdata->abstract = NULL;
  ptr_risdata->title_series = NULL;
  ptr_risdata->booktitle = NULL;
  ptr_risdata->title = NULL;
  ptr_risdata->address = NULL;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  set_risdata_field(): enters the supplied info into the risdata struct
                        the data are properly quoted before adding
			them to the struct

  int set_risdata_field returns 0 if ok, >0 if error
                         error codes: 1 = out of memory

  struct RISDATA* ptr_risdata ptr to structure with field values

  const char* fieldname field specifier

  const char* fieldvalue the data proper

  dbi_conn conn the database connection

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int set_risdata_field(struct RISDATA* ptr_risdata, const char* fieldname, const char* fieldvalue, dbi_conn conn) {
  char* escape_buffer;
  char buffer[256]; /* buffer for log message */

  if (!ptr_risdata
      || !fieldname
      || !*fieldname
      || !fieldvalue
      || !*fieldvalue) {
    /* nothing to do */
    return 0;
  }

  escape_buffer = strdup(fieldvalue);
  if (escape_buffer == NULL) {
    LOG_PRINT(LOG_WARNING, "malloc failed");
    return 1;
  }

  /* escape any characters that the db cannot digest */
  if (dbi_conn_quote_string(conn, &escape_buffer) == 0) {
    free(escape_buffer);
    LOG_PRINT(LOG_WARNING, "malloc failed");
    return 1;
  }

  if (!strcmp(fieldname, "citekey")) {
    strcpy(ptr_risdata->citekey, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "user1")) {
    strcpy(ptr_risdata->user1, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "user2")) {
    strcpy(ptr_risdata->user2, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "user3")) {
    strcpy(ptr_risdata->user3, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "user4")) {
    strcpy(ptr_risdata->user4, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "user5")) {
    strcpy(ptr_risdata->user5, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "issn")) {
    strcpy(ptr_risdata->issn, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "issue")) {
    strcpy(ptr_risdata->issue, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "publisher")) {
    strcpy(ptr_risdata->publisher, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "city")) {
    strcpy(ptr_risdata->city, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "volume")) {
    strcpy(ptr_risdata->volume, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "endpage")) {
    strcpy(ptr_risdata->endpage, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "startpage")) {
    strcpy(ptr_risdata->startpage, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "type")) {
    strcpy(ptr_risdata->type, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "abstract")) {
    ptr_risdata->abstract = escape_buffer;
  }
  else if (!strcmp(fieldname, "title_series")) {
    ptr_risdata->title_series = escape_buffer;
  }
  else if (!strcmp(fieldname, "booktitle")) {
    ptr_risdata->booktitle = escape_buffer;
  }
  else if (!strcmp(fieldname, "title")) {
    ptr_risdata->title = escape_buffer;
  }
  else if (!strcmp(fieldname, "address")) {
    ptr_risdata->address = escape_buffer;
  }
  else if (!strcmp(fieldname, "misc1")) {
/*     printf("type went to %s; value went to %s\n", ptr_risdata->type, truncate_quoted_string(escape_buffer, 255)); */
    if (!strcmp(ptr_risdata->type, "'ART'")
	|| !strcmp(ptr_risdata->type, "'PCOMM'")
	|| !strcmp(ptr_risdata->type, "'RPRT'")) {
      strcpy(ptr_risdata->typeofwork, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'CHAP'")
	     || !strcmp(ptr_risdata->type, "'CONF'")
	     || !strcmp(ptr_risdata->type, "'BOOK'")
	     || !strcmp(ptr_risdata->type, "'SER'")) {
/*       printf("set numvolumes\n"); */
      strcpy(ptr_risdata->numvolumes, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'COMP'")) {
      strcpy(ptr_risdata->computer, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'ELEC'")
	     || !strcmp(ptr_risdata->type, "'JOUR'")) {
      strcpy(ptr_risdata->mediatype, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'ICOMM'")) {
      strcpy(ptr_risdata->senderemail, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'JFULL'")) {
      strcpy(ptr_risdata->registrynum, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'MAP'")) {
      strcpy(ptr_risdata->area, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'MPCT'")
	     || !strcmp(ptr_risdata->type, "'SOUND'")
	     || !strcmp(ptr_risdata->type, "'VIDEO'")) {
      strcpy(ptr_risdata->classification, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'NEWS'")) {
      strcpy(ptr_risdata->issue, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'PAMPH'")) {
      strcpy(ptr_risdata->pamphletnum, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'PAT'")) {
      strcpy(ptr_risdata->classcodeintl, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'THES'")) {
      strcpy(ptr_risdata->degree, truncate_quoted_string(escape_buffer, 255));
    }
    else {
      printf("none matched\n");
    }
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "misc2")) {
    if (!strcmp(ptr_risdata->type, "'CHAP'")) {
      strcpy(ptr_risdata->volume, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'COMP'")) {
      strcpy(ptr_risdata->ostype, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'CONF'")) {
      strcpy(ptr_risdata->conferencelocation, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'ICOMM'")) {
      strcpy(ptr_risdata->recipientemail, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'MAP'")) {
      strcpy(ptr_risdata->mediatype, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'MPCT'")
	     || !strcmp(ptr_risdata->type, "'SOUND'")
	     || !strcmp(ptr_risdata->type, "'VIDEO'")) {
      strcpy(ptr_risdata->runningtime, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'NEWS'")) {
      strcpy(ptr_risdata->section, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'PAT'")) {
      strcpy(ptr_risdata->classcodeus, truncate_quoted_string(escape_buffer, 255));
    }
    else if (!strcmp(ptr_risdata->type, "'THES'")) {
      strcpy(ptr_risdata->typeofwork, truncate_quoted_string(escape_buffer, 255));
    }
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "mediatype")) {
    strcpy(ptr_risdata->mediatype, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "typeofwork")) {
    strcpy(ptr_risdata->typeofwork, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "edition")) {
    strcpy(ptr_risdata->edition, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else if (!strcmp(fieldname, "chapternum")) {
    strcpy(ptr_risdata->chapternum, truncate_quoted_string(escape_buffer, 255));
    free(escape_buffer);
  }
  else {
    snprintf(buffer, 255, "unknown field: %s", fieldname);
    buffer[255] = '\0';
    LOG_PRINT(LOG_DEBUG, buffer);
  }
  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  set_risdata_dateinfo(): sets pubyear and otherinfo fields in risdata struct

  int set_risdata_dateinfo returns 0 if ok, >0 if error
                    error codes: 1 = malloc failed
			       
  struct RISDATA* ptr_risdata ptr to structure with field values

  int year_type 0 = primary, 1 = secondary

  int year the year

  const char* otherinfo string containing otherinfo

  dbi_driver driver ptr to database driver

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int set_risdata_dateinfo(struct RISDATA* ptr_risdata, int date_type, int year, const char* otherinfo, dbi_conn conn) {
  char* escape_buffer;

  if (!ptr_risdata) {
    return 0;
  }

  if (!date_type) {
    ptr_risdata->n_pubyear = year;
  }
  else {
    ptr_risdata->n_secyear = year;
  }

  if (!otherinfo || !*otherinfo) {
    escape_buffer = strdup("///");
  }
  else {
    escape_buffer = strdup(otherinfo);
  }

  if (escape_buffer == NULL) {
    LOG_PRINT(LOG_WARNING, "malloc failed");
    return 1;
  }

  /* escape any characters that the database server cannot digest */
  if (dbi_conn_quote_string(conn, &escape_buffer) == 0) {
    LOG_PRINT(LOG_WARNING, "out of memory");
    free(escape_buffer);
    return 1;
  }

  if (!date_type) {
    strncpy(ptr_risdata->pyother_info, escape_buffer, 255);
    (ptr_risdata->pyother_info)[255] = '\0';
  }
  else {
    strcpy(ptr_risdata->secother_info, escape_buffer);
    (ptr_risdata->secother_info)[255] = '\0';
  }

  free(escape_buffer);

  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  commit_risdata_fields(): updates the t_refdb fields

  int commit_risdata_fields returns 0 if ok, >0 if error
                         error codes: 1 = out of memory
                                      2 = db error

  struct RISDATA* ptr_risdata ptr to structure with field values

  dbi_conn conn the database connection

  int replace_ref if 1, reference is to be replaced
                  if 3, add to temporary table

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int commit_risdata_fields(struct RISDATA* ptr_risdata, dbi_conn conn, int replace_ref) {
  char* sql_command;
  char* new_sql_command;
  char buffer[256]; /* buffer for assembling strings */
  char prefix[] = TEMP_TABLE_NAME_PREFIX;
  size_t sql_cmd_len = 10240;
  dbi_result dbires;

  if (!ptr_risdata) {
    /* nothing to do */
    return 0;
  }
  else if ((sql_command = malloc(sql_cmd_len)) == NULL) {
    LOG_PRINT(LOG_WARNING, "malloc failed");
    return 1;
  }

  /* fix insert */
  if (replace_ref != 3) {
    *prefix = '\0';
  }

  /* fill the command string with the fixed size fields as we know the
     maximum length */
  sprintf(sql_command, "UPDATE t_%srefdb SET refdb_pubyear=%hd, refdb_secyear=%hd, refdb_pyother_info=%s, refdb_secother_info=%s, refdb_citekey=%s, refdb_user1=%s, refdb_user2=%s, refdb_user3=%s, refdb_user4=%s, refdb_user5=%s, refdb_typeofwork=%s, refdb_area=%s, refdb_ostype=%s, refdb_degree=%s, refdb_runningtime=%s, refdb_classcodeintl=%s, refdb_classcodeus=%s, refdb_senderemail=%s, refdb_recipientemail=%s, refdb_mediatype=%s, refdb_numvolumes=%s, refdb_edition=%s, refdb_computer=%s, refdb_conferencelocation=%s, refdb_registrynum=%s, refdb_classification=%s, refdb_section=%s, refdb_pamphletnum=%s, refdb_chapternum=%s, refdb_issn=%s, refdb_issue=%s, refdb_publisher=%s, refdb_city=%s, refdb_volume=%s, refdb_endpage=%s, refdb_startpage=%s, refdb_type=%s", 
	  prefix,
	  ptr_risdata->n_pubyear,
	  ptr_risdata->n_secyear,
	  *(ptr_risdata->pyother_info) ? ptr_risdata->pyother_info : "NULL", 
	  *(ptr_risdata->secother_info) ? ptr_risdata->secother_info : "NULL", 
	  *(ptr_risdata->citekey) ? ptr_risdata->citekey : "NULL", 
	  *(ptr_risdata->user1) ? ptr_risdata->user1 : "NULL", 
	  *(ptr_risdata->user2) ? ptr_risdata->user2 : "NULL", 
	  *(ptr_risdata->user3) ? ptr_risdata->user3 : "NULL", 
	  *(ptr_risdata->user4) ? ptr_risdata->user4 : "NULL", 
	  *(ptr_risdata->user5) ? ptr_risdata->user5 : "NULL", 
	  *(ptr_risdata->typeofwork) ? ptr_risdata->typeofwork : "NULL", 
	  *(ptr_risdata->area) ? ptr_risdata->area : "NULL", 
	  *(ptr_risdata->ostype) ? ptr_risdata->ostype : "NULL", 
	  *(ptr_risdata->degree) ? ptr_risdata->degree : "NULL", 
	  *(ptr_risdata->runningtime) ? ptr_risdata->runningtime : "NULL", 
	  *(ptr_risdata->classcodeintl) ? ptr_risdata->classcodeintl : "NULL", 
	  *(ptr_risdata->classcodeus) ? ptr_risdata->classcodeus : "NULL", 
	  *(ptr_risdata->senderemail) ? ptr_risdata->senderemail : "NULL", 
	  *(ptr_risdata->recipientemail) ? ptr_risdata->recipientemail : "NULL", 
	  *(ptr_risdata->mediatype) ? ptr_risdata->mediatype : "NULL", 
	  *(ptr_risdata->numvolumes) ? ptr_risdata->numvolumes : "NULL", 
	  *(ptr_risdata->edition) ? ptr_risdata->edition : "NULL", 
	  *(ptr_risdata->computer) ? ptr_risdata->computer : "NULL", 
	  *(ptr_risdata->conferencelocation) ? ptr_risdata->conferencelocation : "NULL", 
	  *(ptr_risdata->registrynum) ? ptr_risdata->registrynum : "NULL", 
	  *(ptr_risdata->classification) ? ptr_risdata->classification : "NULL", 
	  *(ptr_risdata->section) ? ptr_risdata->section : "NULL", 
	  *(ptr_risdata->pamphletnum) ? ptr_risdata->pamphletnum : "NULL", 
	  *(ptr_risdata->chapternum) ? ptr_risdata->chapternum : "NULL", 
	  *(ptr_risdata->issn) ? ptr_risdata->issn : "NULL", 
	  *(ptr_risdata->issue) ? ptr_risdata->issue : "NULL", 
	  *(ptr_risdata->publisher) ? ptr_risdata->publisher : "NULL", 
	  *(ptr_risdata->city) ? ptr_risdata->city : "NULL", 
	  *(ptr_risdata->volume) ? ptr_risdata->volume : "NULL", 
	  *(ptr_risdata->endpage) ? ptr_risdata->endpage : "NULL", 
	  *(ptr_risdata->startpage) ? ptr_risdata->startpage : "NULL", 
	  *(ptr_risdata->type) ? ptr_risdata->type : "NULL");

  /* append the variable length fields */
  if (ptr_risdata->abstract && *(ptr_risdata->abstract)) {
    if ((new_sql_command = mstrcat(sql_command, ", refdb_abstract=", &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }

    if ((new_sql_command = mstrcat(sql_command, ptr_risdata->abstract, &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }
  }

  if (ptr_risdata->title_series && *(ptr_risdata->title_series)) {
    if ((new_sql_command = mstrcat(sql_command, ", refdb_title_series=", &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }

    if ((new_sql_command = mstrcat(sql_command, ptr_risdata->title_series, &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }
  }

  if (ptr_risdata->booktitle && *(ptr_risdata->booktitle)) {
    if ((new_sql_command = mstrcat(sql_command, ", refdb_booktitle=", &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }

    if ((new_sql_command = mstrcat(sql_command, ptr_risdata->booktitle, &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }
  }

  if (ptr_risdata->title && *(ptr_risdata->title)) {
    if ((new_sql_command = mstrcat(sql_command, ", refdb_title=", &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }

    if ((new_sql_command = mstrcat(sql_command, ptr_risdata->title, &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }
  }

  if (ptr_risdata->address && *(ptr_risdata->address)) {
    if ((new_sql_command = mstrcat(sql_command, ", refdb_address=", &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }

    if ((new_sql_command = mstrcat(sql_command, ptr_risdata->address, &sql_cmd_len, 0)) == NULL) {
      free(sql_command);
      LOG_PRINT(LOG_WARNING, "malloc failed");
      return 1;
    }
    else {
      sql_command = new_sql_command;
    }
  }

  sprintf(buffer, " WHERE refdb_id="ULLSPEC, (unsigned long long)ptr_risdata->n_id);
  if ((new_sql_command = mstrcat(sql_command, buffer, &sql_cmd_len, 0)) == NULL) {
    free(sql_command);
    LOG_PRINT(LOG_WARNING, "malloc failed");
    return 1;
  }
  else {
    sql_command = new_sql_command;
  }

  LOG_PRINT(LOG_DEBUG, sql_command);

  dbires = dbi_conn_query(conn, sql_command);
  free(sql_command);

  if (!dbires) {
    return 2;
  }
  dbi_result_free(dbires);

  return 0;
}
