/*****************************************************************************
File: sqlmiddlertools.c
Author: Salas Lopez, Jorge
Date:   27/05/2004
Description: Database Library Tools for postgres v7.2.
Invocation:  Nothing
*****************************************************************************/

/*****************************************************************************  
   Table of Contents:
   Reusable Functions:      
    int GetWriteSet(struct DBType *db, char *writeset);
    int SetWriteSet(struct DBType *db, char *writeset, int length);
    char *SQLDeleteTableDB(char *db, char *table);
    char *SQLExistDBInDBSchema(char *db);
    char *SQLInsertTableDB(char *maxid, char *db, char *table);
    char *SQLLastIDCC();
    char *SQLRecordsDBSchema();
    char *SQLTablesDB(); 
   Intern Functions:      
    ---
   Includes:	  
    stdio.h; printf, sprintf
   Source code in this file:
    All
*********************************************************************************/

/********************************************************************************
Import Libraries.
*********************************************************************************/
#include <stdio.h>
#include "database.h"
//#include "tools.h"

/********************************************************************************
Prototype Functions
*********************************************************************************/
int GetWriteSet(struct DBType *db, char *writeset);
int SetWriteSet(struct DBType *db, char *writeset, int length);
char *SQLDeleteTableDB(char *db, char *table);
char *SQLExistDBInDBSchema(char *db);
char *SQLInsertTableDB(char *maxid, char *db, char *table);
char *SQLLastIDCC();
char *SQLRecordsDBSchema();
char *SQLTablesDB();

/********************************************************************************
Defines
*********************************************************************************/
//#define DEBUG_SQLMIDDLERTOOLS
#define GET_WRITESET 2074
#define PUT_WRITESET 2075

/********************
 *  IMPLEMENTATION  *
 *******************/
/********************************************************************************
Reusable Function.
   int GetWriteSet(struct DBType *db, char *writeset);
   Purpose: Get writeset of the last update
   Limitations: Nothing
   Returns: if an error exist return -1
            else return size of writeset
*********************************************************************************/
int GetWriteSet(struct DBType *db, char *writeset)
{ 
  PQArgBlock ar[1];
  int bytes = -1;

  if ((*db).pgdata.connection != NULL){	
    PQfn((*db).pgdata.connection, GET_WRITESET, (int*) writeset, &bytes, 0, ar, 0);
  }

  #ifdef DEBUG_SQLMIDDLERTOOLS
    printf("WriteSet: <%d> <%d>\n", (int*)writeset, bytes);
  #endif
  return bytes;
}

/********************************************************************************
Reusable Function.
   int SetWriteSet(struct DBType *db, char *writeset, int length);
   Purpose: Set writeset of the last update
   Limitations: Nothing
   Returns: if an error exist return -1
            else return size of writeset
*********************************************************************************/
int SetWriteSet(struct DBType *db, char *writeset, int length)
{ 
  PQArgBlock ar[1];
  char dummy[1000];
  int dummy_length;
  int bytes = -1;

  if ((*db).pgdata.connection != NULL){
    if (ExecuteTransaction(db, "BEGIN") == -1){
      return -2;
    }
    FreeResult(db);
    
    ar[0].len = length;
    ar[0].isint=0;
    ar[0].u.ptr = (int*) writeset;
    PQfn((*db).pgdata.connection, PUT_WRITESET, (int*) dummy, &dummy_length, 0, ar, 1);
    
    /* PostgresSql v72 needs end after SET WRITESET to force commit changes in database */
    if (ExecuteTransaction(db, "END") == -1){
      return -3;
    }
    FreeResult(db);
    bytes = 0;
  }
  return bytes;
}

/********************************************************************************
Reusable Function.
   char *SQLDeleteTableDB(char *db, char *table);
   Purpose: Get sentence sql for delete table in database replicated
   Limitations: Nothing
   Returns: sentence sql -> "insert into conflict_classes values (maxid, 'db', 'table')
*********************************************************************************/
char *SQLDeleteTableDB(char *db, char *table)
{
  char *sqlcode = NULL;
  if (!(sqlcode = (char*) malloc(sizeof(char) * (strlen(db) + strlen(table) + 70 /* 65 const char */)))) {
    printf ( "%s# %d # Out of memory.\n", __FILE__, __LINE__ );
  }

  strcpy (sqlcode, "delete from conflict_classes where dbname = '");
  strcat (sqlcode, db);
  strcat (sqlcode, "' and tablename = '");
  strcat (sqlcode, table);
  strcat (sqlcode, "'");

  #ifdef DEBUG_SQLMIDDLERTOOLS
    printf("SQL Delete: <%s>\n", sqlcode);
  #endif
  return sqlcode;
}

/********************************************************************************
Reusable Function.
   char *SQLExistDBInDBSchema(char *db);
   Purpose: Get sentence sql for delete table in database replicated
   Limitations: Nothing
   Returns: sentence sql -> "insert into conflict_classes values (maxid, 'db', 'table')
*********************************************************************************/
char *SQLExistDBInDBSchema(char *db)
{
  char *sqlcode = NULL;
  if (!(sqlcode = (char*) malloc(sizeof(char) * (strlen(db) + 55 /* 52 const char */)))) {
    printf ( "%s# %d # Out of memory.\n", __FILE__, __LINE__ );
  }

  strcpy (sqlcode, "select id_cc from conflict_classes where dbname = '");
  strcat (sqlcode, db);
  strcat (sqlcode, "'");

  #ifdef DEBUG_SQLMIDDLERTOOLS
    printf("SQL Exist: <%s>\n", sqlcode);
  #endif
  return sqlcode;
}

/********************************************************************************
Reusable Function.
   char *SQLInsertTableDB(char *maxid, char *db, char *table);
   Purpose: Get sentence sql for insert table in database replicated
   Limitations: Nothing
   Returns: sentence sql -> "insert into conflict_classes values (maxid, 'db', 'table')
*********************************************************************************/
char *SQLInsertTableDB(char *maxid, char *db, char *table)
{
  char *sqlcode = NULL;
  if (!(sqlcode = (char*) malloc(sizeof(char) * (strlen(maxid) + strlen(db) + strlen(table) + 50 /* 45 const char */)))) {
    printf ( "%s# %d # Out of memory.\n", __FILE__, __LINE__ );
  }
  
  strcpy (sqlcode, "insert into conflict_classes values (");
  strcat (sqlcode, maxid);
  strcat (sqlcode, ",'");
  strcat (sqlcode, db);
  strcat (sqlcode, "', ");
  strcat (sqlcode, "'");
  strcat (sqlcode, table);
  strcat (sqlcode, "')");

  #ifdef DEBUG_SQLMIDDLERTOOLS
    printf("SQL Insert Table: <%s>\n", sqlcode);
  #endif
  return sqlcode;
}

/********************************************************************************
Reusable Function.
   char *SQLLastIDCC();
   Purpose: Get sentence sql for get the last id_cc in database schema
   Limitations: Nothing
   Returns: sentence sql -> "select MAX(id_cc) from conflict_classes"
*********************************************************************************/
char *SQLLastIDCC()
{
  return "select MAX(id_cc) from conflict_classes";
}

/********************************************************************************
Reusable Function.
   char *SQLRecordsDBSchema();
   Purpose: Get sentence sql for get records of database schema
   Limitations: Nothing
   Returns: sentence sql -> "select dbname, tablename, id_cc from conflict_classes"
*********************************************************************************/
char *SQLRecordsDBSchema()
{
  return "select dbname, tablename, id_cc from conflict_classes";
}

/********************************************************************************
Reusable Function.
   char *SQLTablesDB();
   Purpose: Get sentence sql for get all tables in replicated database
   Limitations: Nothing
   Returns: sentence sql -> "select relname from pg_class where relkind = 'r'"
*********************************************************************************/
char *SQLTablesDB()
{
  return "select relname from pg_class where relkind = 'r'";
}
