db.c

text/plain

Filename: db.c
Type: text/plain
Part: 3
Message: PostgreSQL program question.
#include <pgsql/libpq-fe.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include "db.h"

static PGconn *conn;
static PGresult *res;

static int connectDB() {
  char * dbName = "some_db";
  char * pguser = "some_user";
  char * pgpasswd = "some_passwd";
  
  conn = PQsetdbLogin(NULL, NULL, NULL, NULL, dbName, pguser, pgpasswd);
  
  if (PQstatus(conn) == CONNECTION_BAD) {
    fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
    fprintf(stderr, "%s", PQerrorMessage(conn));
    return -1;
  }
  
  return 1; 
}

static void disconnectDB() {
  PQfinish(conn);
}

static int startTransaction() {
  int ret = 1;

  res = PQexec(conn, "BEGIN");
  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
    fprintf(stderr, "BEGIN command failed\n");
    ret = -1;
  }                                         
  PQclear(res);
  
  return ret;
}

static void commitTransaction() {
  res = PQexec(conn, "CLOSE mc");
  PQclear(res);
  res = PQexec(conn, "COMMIT");
  PQclear(res);          
}

static char * getString(int tup, int field) {
  char * ret;
  int n = PQgetlength(res, tup, field);
  ret = strncpy(malloc(n+1), PQgetvalue(res, tup, field), n);
  ret[n] = 0;
  
  return ret;
}

static int execCountSelect(const char * sql) {
  char runSQL[1024];
  int ret = 0;
  
  if (startTransaction()) {
    strcpy(runSQL, "DECLARE mc CURSOR FOR ");
    strcat(runSQL, sql);
    res = PQexec(conn, runSQL);
    if (PQresultStatus(res) == PGRES_COMMAND_OK) {       
      PQclear(res);
      res = PQexec(conn, "FETCH ALL in mc");
      if (PQresultStatus(res) == PGRES_TUPLES_OK)
        ret = atoi(PQgetvalue(res, 0, 0));
    }
  }
  PQclear(res);
  commitTransaction();
  
  return ret;
}

static int execSQL(const char * sql) {
  int ret = -1;
  char runSQL[1024];
  
  if (startTransaction()) {
    strcpy(runSQL, "DECLARE mc CURSOR FOR ");
    strcat(runSQL, sql);
    PQexec(conn, runSQL);
    if (PQresultStatus(res) == PGRES_COMMAND_OK)
      ret = 1;
  }
  PQclear(res);
  
  return ret;
}

static int fetchNext() {
  res = PQexec(conn, "FETCH FORWARD 1 IN mc");
  if (PQresultStatus(res) == PGRES_TUPLES_OK) return 1;
  else return -1;  
}

static char * getCurTime() {
  time_t curTime;
  char * ret;

  ret = (char *)malloc(6);

  time(&curTime);
   
  strftime(ret, 6, "%H:%M", localtime(&curTime));

  return ret;
}

testStruct * getAllowTest(const char * loginName, int * num) {
  testStruct * ret;
  char sql[500], * desc, * curTime;
  int i = 0;

  ret = NULL;
  *num = 0;
  curTime = getCurTime();

  if (connectDB()) {
    sprintf(sql,

"SELECT Count(Id_Test) FROM Run_Test \
 WHERE Run_Test.Id_Student=Student.Id \
 AND Student.Name='%s' AND \
 Run_Test.startTime <= '%s' AND \
 Run_Test.stopTime >= '%s'", 

    loginName, curTime, curTime);
    *num = execCountSelect(sql);
    if (*num != 0) {
    
      sprintf(sql, 
"SELECT * FROM Test \
 WHERE Test.Id IN \
   (SELECT Id_Test FROM Run_Test \
      WHERE Run_Test.Id_Student=Student.Id AND \
 Student.Name='%s' AND Run_Test.startTime <= '%s' AND \
 Run_Test.stopTime >= '%s')", 
      loginName, curTime, curTime);
      
      if (execSQL(sql)) {
        ret = (testStruct *)calloc(sizeof(testStruct), *num);
        while (i < *num)
          if (fetchNext()) {
            ret[i].id = atoi(PQgetvalue(res, 0, 0));
            ret[i].testNum = atoi(PQgetvalue(res, 0, 2));
            desc = PQgetvalue(res, 0, 3);
            ret[i++].Description = strcpy(malloc(strlen(desc)+1), desc);
            PQclear(res);
          }
          else break;        
        PQclear(res);
        commitTransaction();
      }
    }
  }

 free(curTime);
 disconnectDB();
 return ret;
}

questionStruct * getQuestion(const int idTest, int * num) {
  questionStruct * ret;
  int i = 0, j;
  char sql[500], * buf;
  
  ret = 0;
  *num = 0;
  
  if (connectDB()) {
  
    sprintf(sql, "SELECT Count(id) FROM Question WHERE Id_Test = %d", idTest);
    *num = execCountSelect(sql);
    
    if (*num != 0) {
      sprintf(sql, "SELECT * FROM Question WHERE Id_Test=%d GROUP BY Id", idTest);
      if (execSQL(sql)) {
        ret = (questionStruct *)calloc(sizeof(questionStruct), *num);
        while (i < *num)
          if (fetchNext()) {
            ret[i].id = atoi(PQgetvalue(res, 0, 0));
            ret[i].text = getString(0, 2);
            ret[i].question = getString(0, 3);            
            ret[i++].bonus = atoi(PQgetvalue(res, 0, 4));
            //PQclear(res); /* Something not wrong here??? */
          }
          else i = *num;
        commitTransaction();
      }
      
      for (i = 0; i < *num; i++) {
        sprintf(sql, "SELECT * FROM Answer WHERE Id_Question=%d GROUP BY Id", 
                ret[i].id);
        if (execSQL(sql)) {
          res = PQexec(conn, "FETCH ALL IN mc");
          if (PQresultStatus(res) == PGRES_TUPLES_OK) {
            ret[i].numAnswers = PQntuples(res);
            ret[i].answers = (answerStruct *)calloc(sizeof(answerStruct), ret[i].numAnswers);
            for (j = 0; j < ret[i].numAnswers; j++) {
              ret[i].answers[j].text = getString(j, 2);
              buf = getString(j, 3);
              ret[i].answers[j].answer = *buf == 't' ? 1 : 0;
              free(buf);
            }          
          }
          PQclear(res);
          commitTransaction();
        }
      }
    }
  }
  
  disconnectDB();
  return ret;
}

void writeResult(const int idTest, const char *loginName, const int result) {
}