wileymud-1.187b/
wileymud-1.187b/attic/
wileymud-1.187b/attic/bin/
wileymud-1.187b/attic/lib/
wileymud-1.187b/attic/lib/adm/
wileymud-1.187b/attic/lib/man/
wileymud-1.187b/attic/lib/new-wld/
wileymud-1.187b/attic/lib/new-wld/default/
wileymud-1.187b/attic/lib/old/
wileymud-1.187b/attic/lib/wld/
wileymud-1.187b/attic/public_html/
wileymud-1.187b/attic/public_html/gfx/
wileymud-1.187b/attic/src/bin/
wileymud-1.187b/attic/src/etc/
wileymud-1.187b/attic/src/libauth-4.0-p5/
wileymud-1.187b/attic/src/sedna/
wileymud-1.187b/backups/
wileymud-1.187b/bin/
wileymud-1.187b/docs/
wileymud-1.187b/etc/
wileymud-1.187b/lib/
wileymud-1.187b/lib/adm/
wileymud-1.187b/lib/boards/
wileymud-1.187b/lib/log/
wileymud-1.187b/lib/man/
wileymud-1.187b/lib/ply/
wileymud-1.187b/lib/ply/a/
wileymud-1.187b/lib/ply/b/
wileymud-1.187b/lib/ply/c/
wileymud-1.187b/lib/ply/d/
wileymud-1.187b/lib/ply/g/
wileymud-1.187b/lib/ply/k/
wileymud-1.187b/lib/ply/m/
wileymud-1.187b/lib/ply/s/
wileymud-1.187b/lib/ply/t/
wileymud-1.187b/public_html/gfx/
wileymud-1.187b/src/bin/
wileymud-1.187b/src/convert/attic/
wileymud-1.187b/src/convert/obj/
wileymud-1.187b/src/convert/perl/
wileymud-1.187b/src/convert/perl/MudConvert/
wileymud-1.187b/src/convert/perl/MudConvert/DUMP/
wileymud-1.187b/src/convert/perl/MudConvert/Report/
wileymud-1.187b/src/convert/perl/MudConvert/WileyMUD/
wileymud-1.187b/src/convert/perl/output/
wileymud-1.187b/src/convert/perl/output/DUMP/
wileymud-1.187b/src/convert/perl/output/Report/
wileymud-1.187b/src/convert/perl/output/WileyMUD/
wileymud-1.187b/src/etc/
wileymud-1.187b/src/etc/init.d/
wileymud-1.187b/src/etc/rc.d/
wileymud-1.187b/src/etc/rc.d/init.d/
wileymud-1.187b/src/lib/
wileymud-1.187b/src/lib/adm/
wileymud-1.187b/src/lib/boards/
wileymud-1.187b/src/lib/log/
wileymud-1.187b/src/lib/man/
wileymud-1.187b/src/lib/ply/
wileymud-1.187b/src/lib/ply/a/
wileymud-1.187b/src/lib/ply/b/
wileymud-1.187b/src/lib/ply/c/
wileymud-1.187b/src/lib/ply/d/
wileymud-1.187b/src/lib/ply/e/
wileymud-1.187b/src/lib/ply/f/
wileymud-1.187b/src/lib/ply/g/
wileymud-1.187b/src/lib/ply/h/
wileymud-1.187b/src/lib/ply/i/
wileymud-1.187b/src/lib/ply/j/
wileymud-1.187b/src/lib/ply/k/
wileymud-1.187b/src/lib/ply/l/
wileymud-1.187b/src/lib/ply/m/
wileymud-1.187b/src/lib/ply/n/
wileymud-1.187b/src/lib/ply/o/
wileymud-1.187b/src/lib/ply/p/
wileymud-1.187b/src/lib/ply/q/
wileymud-1.187b/src/lib/ply/r/
wileymud-1.187b/src/lib/ply/s/
wileymud-1.187b/src/lib/ply/t/
wileymud-1.187b/src/lib/ply/u/
wileymud-1.187b/src/lib/ply/v/
wileymud-1.187b/src/lib/ply/w/
wileymud-1.187b/src/lib/ply/x/
wileymud-1.187b/src/lib/ply/y/
wileymud-1.187b/src/lib/ply/z/
wileymud-1.187b/src/obj/
wileymud-1.187b/src/utils/
wileymud-1.187b/src/utils/mobmaker/
/*
 * SQuirreLMUD 1.0 - Copyright (C) 2003 - Chris Meshkin
 *
 * This is the low-level SQL interface code for PostgreSQL 7.x
 *
 * File:        $Source: /home/cvs/root/squirrel/src/sql.c,v $
 * Revision:    $Revision: 1.2 $
 * Date:        $Date: 2003/07/26 06:28:08 $
 * Author:      $Author: quixadhal $
 * CVS_ID:      $Id: sql.c,v 1.2 2003/07/26 06:28:08 quixadhal Exp $
 * $Log: sql.c,v $
 * Revision 1.2  2003/07/26 06:28:08  quixadhal
 * Progress, now have a working bug system
 *
 * Revision 1.1  2003/07/26 03:57:39  quixadhal
 * Version 0
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

/* #include "config.h" */
#include "mud.h"

/* #define TESTING */

#define _SQL_C
#include "sql.h"

#ifdef USE_POSTGRES
PGconn *dbc = NULL;
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
sql_connect_data pgcdata = {
  DBHOST,
  DBPORT,
  DBNAME,
  DBOPTS,
  DBUSER,
  DBPASS
};

PGconn *sql_open(sql_connect_data *cdata)
{
  char *s = NULL;

  dbc = PQsetdbLogin(cdata->dbhost, cdata->dbport,
                     cdata->dbopts,
                     NULL, cdata->dbname,
                     cdata->dbuser, cdata->dbpasswd);
  if(dbc) {
    s = sql_version();
    if(!s || !*s) {
      sql_close();
      dbc = NULL;
      return NULL;
    }
  }
  return dbc;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
void sql_close(void)
{
  if(dbc) {
    PQfinish(dbc);
  }
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
char *sql_error(ExecStatusType estat)
{
  static char last_err[GIANT_BUF];
  char *err_str = NULL;
  char *pgerr = NULL;

  if(estat) err_str = PQresStatus(estat);
  if(dbc) pgerr = PQerrorMessage(dbc);
  bzero(last_err, GIANT_BUF);
  snprintf(last_err, GIANT_BUF-1, "%s%s%s",
           err_str?err_str:"",
           pgerr?" ":"",
           pgerr?pgerr:"");

#ifndef TESTING
  log_string("SQL: %s", last_err);
#else
  printf("SQL: %s\n", last_err);
#endif
  return last_err;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
int sql_execute(const char *query, ... )
{
  PGresult *rs = NULL;
  ExecStatusType rstat;
  long int rows = 0;
  char tmp[GIANT_BUF];
  va_list param;

  if(!dbc)
    return -1;
  if(PQstatus(dbc) == CONNECTION_BAD)
    return -1;

  va_start( param, query );
  vsnprintf( tmp, GIANT_BUF, query, param );
  va_end( param );

  rs = PQexec(dbc, "BEGIN");
  if ((rstat = PQresultStatus(rs)) != PGRES_COMMAND_OK) {
    PQclear(rs);
    sql_error(rstat);
    return -1;
  }
  PQclear(rs);
  rs = PQexec(dbc, tmp);
  if ((rstat = PQresultStatus(rs)) != PGRES_COMMAND_OK) {
    PQclear(rs);
    sql_error(rstat);
    rs = PQexec(dbc, "ROLLBACK");
    PQclear(rs);
    return -1;
  } else {
    rows = atol(PQcmdTuples(rs));
  }
  PQclear(rs);
  rs = PQexec(dbc, "COMMIT");
  if ((rstat = PQresultStatus(rs)) != PGRES_COMMAND_OK) {
    PQclear(rs);
    sql_error(rstat);
    return -1;
  }
  PQclear(rs);
  return rows;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
sql_query_result * sql_query(const char *query, ... )
{
  PGresult *rs = NULL;
  ExecStatusType rstat;
  char tmp[GIANT_BUF];
  char tquery[GIANT_BUF];
  va_list param;
  sql_query_result *result = NULL;
  register int i;
  register int j;

  if(!dbc)
    return NULL;
  if(PQstatus(dbc) == CONNECTION_BAD)
    return NULL;

  snprintf( tquery, GIANT_BUF, "DECLARE bucket CURSOR FOR %s", query );

  va_start( param, query );
  vsnprintf( tmp, GIANT_BUF, tquery, param );
  va_end( param );

  rs = PQexec(dbc, "BEGIN");
  if ((rstat = PQresultStatus(rs)) != PGRES_COMMAND_OK) {
    PQclear(rs);
    sql_error(rstat);
    return NULL;
  }
  PQclear(rs);

  rs = PQexec(dbc, tmp);
  if ((rstat = PQresultStatus(rs)) != PGRES_COMMAND_OK) {
    PQclear(rs);
    sql_error(rstat);
    rs = PQexec(dbc, "ROLLBACK");
    PQclear(rs);
    return NULL;
  }
  PQclear(rs);
  rs = PQexec(dbc, "FETCH ALL IN bucket");
  if ((rstat = PQresultStatus(rs)) != PGRES_TUPLES_OK) {
    PQclear(rs);
    sql_error(rstat);
    rs = PQexec(dbc, "ROLLBACK");
    PQclear(rs);
    return NULL;
  }

  result = (sql_query_result *)calloc(1, sizeof(sql_query_result *));
  result->cols = PQnfields(rs);
  result->rows = PQntuples(rs);
  result->data = (char ***) calloc(result->rows, sizeof(char **));
  for(i = 0; i < result->rows; i++) {
    result->data[i] = (char **) calloc(result->cols, sizeof(char *));
    for(j = 0; j < result->cols; j++) {
      result->data[i][j] = (char *)strdup(PQgetvalue(rs, i, j));
    }
  }

  PQclear(rs);
  rs = PQexec(dbc, "CLOSE bucket");
  PQclear(rs);
  rs = PQexec(dbc, "END");
  PQclear(rs);

  return result;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
void sql_free_result(sql_query_result *result)
{
  register int i;
  register int j;

  if(result) {
    if(result->data) {
      for(i = 0; i < result->rows; i++) {
        if(result->data[i]) {
          for(j = 0; j < result->cols; j++) {
            if(result->data[i][j])
              free(result->data[i][j]);
          }
          free(result->data[i]);
        }
      }
      free(result->data);
    }
    free(result);
  }
  return;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
char *sql_last_error(void)
{
  static char last_err[GIANT_BUF];
  char *pgerr = NULL;

  if(!dbc)
    return "No database handle!";
  pgerr = PQerrorMessage(dbc);
  if(pgerr && *pgerr) {
    strncpy(last_err, pgerr, GIANT_BUF-1);
  } else {
    bzero(last_err, GIANT_BUF);
  }
  return last_err;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
const char *sql_escape(const char *str)
{
  static char to[GIANT_BUF*2 +1];
  char from[GIANT_BUF];
  size_t to_len = 0;

  bzero(from, GIANT_BUF);
  strncpy(from, str, GIANT_BUF-1);
  to_len = PQescapeString(to, from, strlen(from));
  return to;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
char *sql_version(void)
{
  static char version[GIANT_BUF];
  PGresult *rs = NULL;
  ExecStatusType rstat;

  bzero(version, GIANT_BUF);
  if (dbc) {
    if (PQstatus(dbc) == CONNECTION_OK) {
      rs = PQexec(dbc, "BEGIN");
      if ((rstat = PQresultStatus(rs)) == PGRES_COMMAND_OK) {
        PQclear(rs);
        rs = PQexec(dbc, "DECLARE mycurser CURSOR FOR select version()");
	if ((rstat = PQresultStatus(rs)) == PGRES_COMMAND_OK) {
          PQclear(rs);
          rs = PQexec(dbc, "FETCH ALL in mycurser");
	    if ((rstat = PQresultStatus(rs)) == PGRES_TUPLES_OK) {
            strncpy(version, PQgetvalue(rs, 0, 0), GIANT_BUF);
            version[GIANT_BUF-1] = '\0';
          } else {
            version[0] = '\0';
            sql_error(rstat);
          }
          PQclear(rs);
          rs = PQexec(dbc, "CLOSE mycurser");
          PQclear(rs);
          rs = PQexec(dbc, "END");
        } else {
          sql_error(rstat);
        }
      } else {
        sql_error(rstat);
      }
      PQclear(rs);
    }
  }
  return version;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
char *sql_status(void)
{
  static char sbuf[GIANT_BUF];

  bzero(sbuf, GIANT_BUF);
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "Database Type", "PostgreSQL");
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "Host", PQhost(dbc));
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "Port", PQport(dbc));
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "Database", PQdb(dbc));
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "User", PQuser(dbc));
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "Password", PQpass(dbc));
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "TTY", PQtty(dbc));
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "Options", PQoptions(dbc));
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %d\n", "Backend PID", PQbackendPID(dbc));
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %d\n", "PID", getpid());
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "Last Error", sql_last_error());
  snprintf( sbuf + strlen(sbuf), GIANT_BUF - strlen(sbuf),
            "%20.20s: %s\n", "Version", sql_version());
  return sbuf;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
pid_t sql_backend(void)
{
  return (pid_t) PQbackendPID(dbc);
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
int sql_table_exists(char *table)
{
  PGresult *rs = NULL;
  ExecStatusType rstat;
  char sqlbuf[GIANT_BUF];
  int result = 0;

  bzero(sqlbuf, GIANT_BUF);
  if (dbc && table && *table) {
    if (PQstatus(dbc) == CONNECTION_OK) {
      rs = PQexec(dbc, "BEGIN");
      if ((rstat = PQresultStatus(rs)) == PGRES_COMMAND_OK) {
        PQclear(rs);
        snprintf(sqlbuf, GIANT_BUF, "DECLARE mycurser CURSOR FOR "
                 "SELECT relname FROM pg_class WHERE relname = '%s'",
                 table);
        rs = PQexec(dbc, sqlbuf);
	if ((rstat = PQresultStatus(rs)) == PGRES_COMMAND_OK) {
          PQclear(rs);
          rs = PQexec(dbc, "FETCH ALL in mycurser");
	  if ((rstat = PQresultStatus(rs)) == PGRES_TUPLES_OK) {
            if(PQntuples(rs) > 0) 
              result = 1;
          } else {
            sql_error(rstat);
          }
          PQclear(rs);
          rs = PQexec(dbc, "CLOSE mycurser");
          PQclear(rs);
          rs = PQexec(dbc, "END");
        } else {
          sql_error(rstat);
        }
      } else {
        sql_error(rstat);
      }
      PQclear(rs);
    }
  }
  return result;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
int sql_field_exists(char *table, char *field)
{
  PGresult *rs = NULL;
  ExecStatusType rstat;
  char sqlbuf[GIANT_BUF];
  int result = 0;

  bzero(sqlbuf, GIANT_BUF);
  if (dbc && table && *table && field && *field) {
    if (PQstatus(dbc) == CONNECTION_OK) {
      rs = PQexec(dbc, "BEGIN");
      if ((rstat = PQresultStatus(rs)) == PGRES_COMMAND_OK) {
        PQclear(rs);
        snprintf(sqlbuf, GIANT_BUF, "DECLARE mycurser CURSOR FOR "
                 "SELECT * FROM %s LIMIT 1",
                 table);
        rs = PQexec(dbc, sqlbuf);
	if ((rstat = PQresultStatus(rs)) == PGRES_COMMAND_OK) {
          PQclear(rs);
          rs = PQexec(dbc, "FETCH ALL in mycurser");
	  if ((rstat = PQresultStatus(rs)) == PGRES_TUPLES_OK) {
            if(PQfnumber(rs, field) >= 0)
              result = 1;
          } else {
            sql_error(rstat);
          }
          PQclear(rs);
          rs = PQexec(dbc, "CLOSE mycurser");
          PQclear(rs);
          rs = PQexec(dbc, "END");
        } else {
          sql_error(rstat);
        }
      } else {
        sql_error(rstat);
      }
      PQclear(rs);
    }
  }
  return result;
}
#endif /* USE_POSTGRES */

#ifdef USE_POSTGRES
int sql_truncate(char *table)
{
  PGresult *rs = NULL;
  ExecStatusType rstat;
  char query[GIANT_BUF];

  bzero(query, GIANT_BUF);
  if(!dbc)
    return 0;
  if(PQstatus(dbc) == CONNECTION_BAD)
    return 0;

  rs = PQexec(dbc, "BEGIN");
  if ((rstat = PQresultStatus(rs)) != PGRES_COMMAND_OK) {
    PQclear(rs);
    sql_error(rstat);
    return 0;
  }
  PQclear(rs);
  snprintf(query, GIANT_BUF, "TRUNCATE %s", table);
  rs = PQexec(dbc, query);
  if ((rstat = PQresultStatus(rs)) != PGRES_COMMAND_OK) {
    PQclear(rs);
    sql_error(rstat);
    rs = PQexec(dbc, "ROLLBACK");
    PQclear(rs);
    return 0;
  }
  PQclear(rs);
  rs = PQexec(dbc, "COMMIT");
  if ((rstat = PQresultStatus(rs)) != PGRES_COMMAND_OK) {
    PQclear(rs);
    sql_error(rstat);
    return 0;
  }
  PQclear(rs);
  return 1;
}
#endif /* USE_POSTGRES */

#ifdef TESTING
int main(int argc, char **argv)
{
  sql_query_result *result = NULL;
  sql_connect_data connect_me = {
    NULL, NULL, "socketmud", NULL, "quixadhal", NULL
  };
  register int i = 0;
  register int j = 0;

  sql_open(&connect_me);
  printf("%s\n", sql_status());
  printf("foo exists: %d\n", sql_table_exists("foo"));
  printf("log_types exists: %d\n", sql_table_exists("log_types"));
  printf("foo exists: %d\n", sql_table_exists("foo"));
  result = sql_query("SELECT * FROM log_types ORDER BY log_type_id");
  if(result) {
    if(result->data) {
      for(i = 0; i < result->rows; i++) {
        if(result->data[i]) {
          printf("row %d:\t", i);
          for(j = 0; j < result->cols; j++) {
            if(result->data[i][j])
              printf("%s\t", result->data[i][j]);
          }
          printf("%s", "\n");
        }
      }
    }
  } else {
    printf("%s\n", sql_last_error());
  }
  sql_free_result(result);
  result = NULL;
  sql_close();
  return 1;
}
#endif /* TESTING */