Index: /trunk/psLib/src/db/psDB.c
===================================================================
--- /trunk/psLib/src/db/psDB.c	(revision 7385)
+++ /trunk/psLib/src/db/psDB.c	(revision 7386)
@@ -12,6 +12,6 @@
  *  @author Joshua Hoblitt
  *
- *  @version $Revision: 1.55 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-07 03:30:45 $
+ *  @version $Revision: 1.56 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-07 03:40:43 $
  *
  *  Copyright 2005 Joshua Hoblitt, University of Hawaii
@@ -469,8 +469,447 @@
                         unsigned long long limit)
 {
+    // Create select row query
+    char *query = psDBGenerateSelectRowSQL(tableName, NULL, where, limit);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
+        return NULL;
+    }
+
+    // Run SQL query
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "Query execution failed.");
+        psFree(query);
+        return NULL;
+    }
+    psFree(query);
+
+    // return the result
+    return p_psDBFetchResult(dbh);
+}
+
+bool psDBInsertOneRow(psDB *dbh,
+                      const char *tableName,
+                      const psMetadata *row)
+{
+    psArray         *rowSet;           // psArray of row to insert
+
+    // Check for null row
+    if(row == NULL) {
+        psError(PS_ERR_UNKNOWN,true,PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
+        return false;
+    }
+
+    // Create array to store single row
+    rowSet = psArrayAlloc(1);
+    rowSet->n = 0;
+    psArrayAdd(rowSet, 0, (psPtr)row);
+
+    // Execute function to insert rows
+    if (!psDBInsertRows(dbh, tableName, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool psDBInsertRows(psDB *dbh,
+                    const char *tableName,
+                    const psArray *rowSet)
+{
+    psMetadata      *row;               // row of data
+    char            *query;             // SQL query
+    MYSQL_STMT      *stmt;              // prepared db statement
+    MYSQL_BIND      *bind;              // field values to insert
+    unsigned long   paramCount;         // number of placeholders in query
+    psU64           j;                  // row index
+
+    // Verify database connections is set up
+    if(dbh == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
+        return false;
+    }
+
+    // Verify row array is non-NULL
+    if(rowSet == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
+        return false;
+    }
+
+    // we are assuming that all rows in the set have an identical with reguard
+    // to field count and type
+    row = rowSet->data[0];
+
+    // Generate SQL query string
+    query = psDBGenerateInsertRowSQL(tableName, row);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, PS_ERRORTEXT_psDB_QUERY_GEN_FAIL);
+        return false;
+    }
+
+    // Prepare SQL statement
+    stmt = mysql_stmt_init(dbh->mysql);
+    if (!stmt) {
+        psAbort(__func__, "mysql_stmt_init(), out of memory.");
+    }
+    if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
+        psError(PS_ERR_UNKNOWN, true, "Failed to prepare query.  Error: %s", mysql_stmt_error(stmt));
+        mysql_stmt_close(stmt);
+        psFree(query);
+        return false;
+    }
+
+    psFree(query);
+
+    // how many place holders are in our query
+    paramCount = mysql_stmt_param_count(stmt);
+
+    // structure larger enough to hold one field of data per place holder
+    bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
+
+    // loop over rows
+    for (j = 0; j < rowSet->n; j++) {
+        row = rowSet->data[j];
+
+        // reset bind for each row
+        memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
+
+        if (!psDBPackRow(bind, row, paramCount)) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to pack params into bind structure.");
+
+            mysql_rollback(dbh->mysql);
+
+            psFree(bind);
+            mysql_stmt_close(stmt);
+        }
+
+        if (mysql_stmt_bind_param(stmt, bind)) {
+            psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
+
+            mysql_rollback(dbh->mysql);
+
+            psFree(bind);
+            mysql_stmt_close(stmt);
+
+            return false;
+        }
+
+        if (mysql_stmt_execute(stmt)) {
+            psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
+                    mysql_stmt_error(stmt));
+
+            mysql_rollback(dbh->mysql);
+
+            psFree(bind);
+            mysql_stmt_close(stmt);
+
+            return false;
+        }
+    } // end loop over rows
+
+    psFree(bind);
+    mysql_stmt_close(stmt);
+
+    return true;
+}
+
+psArray *psDBDumpRows(psDB *dbh,
+                      const char *tableName)
+{
+    return psDBSelectRows(dbh, tableName, NULL, 0);
+}
+
+psMetadata *psDBDumpCols(psDB *dbh,
+                         const char *tableName)
+{
+    MYSQL_RES       *result;
+    MYSQL_FIELD     *field;
+    unsigned int    fieldCount;
+    psMetadata      *table;
+    psU32           pType;
+    unsigned int    i;
+    psPtr           column;
+
+    // Verify database object is not null
+    if(dbh == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
+        return NULL;
+    }
+
+    // Verify table name is not null
+    if(tableName == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_NULL_TABLE);
+        return NULL;
+    }
+
+    // find column types
+    result = mysql_list_fields(dbh->mysql, tableName, NULL);
+    if (!result) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Failed to retrieve column types.");
+    }
+
+    field = mysql_fetch_fields(result);
+    fieldCount = mysql_num_fields(result);
+
+    table = psMetadataAlloc();
+
+    // fetch each column and load into psMetadata
+    for (i =0; i < fieldCount; i++) {
+        // find ptype of column
+        pType = psDBMySQLToPType(field[i].type, field[i].flags);
+        //psLogMsg( __func__, PS_LOG_INFO, "pType=[%ld]\n", pType );
+
+        // if the ptype is PS_TYPE_PTR assume that it's a string and fetch the
+        // column as an psArray of strings; otherwise fetch the column as a
+        // psVector.
+        if (pType == PS_DATA_STRING) {
+            // PS_DATA_UNKNOWN -> PS_DATA_ARRAY ?
+            column = psDBSelectColumn(dbh, tableName, field[i].name, 0);
+            psMetadataAddArray(table, PS_LIST_TAIL, field[i].name, 0, "", column);
+            //            psMetadataAddStr(table, PS_LIST_TAIL, field[i].name, "", column);
+            psFree(column);
+        } else {
+            column = psDBSelectColumnNum(dbh, tableName, field[i].name, pType, 0);
+            psMetadataAddVector(table, PS_LIST_TAIL, field[i].name, 0, "", column);
+            psFree(column);
+        }
+    }
+
+    return table;
+}
+
+long psDBUpdateRows(psDB *dbh,
+                    const char *tableName,
+                    const psMetadata *where,
+                    const psMetadata *values)
+{
+    char            *query;
+    MYSQL_STMT      *stmt;              // prepared db statement
+    unsigned long   paramCount;         // number of placeholders in query
+    MYSQL_BIND      *bind;              // field values to insert
+    my_ulonglong    rowsAffected;       // number of rows affected by query
+
+    // Verify database object is not NULL
+    if(dbh == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
+        return -1;
+    }
+
+    // Generate SQL query to update row
+    query = psDBGenerateUpdateRowSQL(tableName, where, values);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, PS_ERRORTEXT_psDB_QUERY_GEN_FAIL);
+        return -1;
+    }
+
+    // Initialize SQL statement
+    stmt = mysql_stmt_init(dbh->mysql);
+    if (!stmt) {
+        psAbort(__func__, "mysql_stmt_init(), out of memory.");
+    }
+
+    // Prepare SQL statement
+    if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
+        psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_PREPARE_FAIL, mysql_stmt_error(stmt));
+        mysql_stmt_close(stmt);
+        psFree(query);
+        return -1;
+    }
+    psFree(query);
+
+    // how many place holders are in our query
+    paramCount = mysql_stmt_param_count(stmt);
+
+    // structure large enough to hold one field of data per place holder
+    bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
+
+    // init bind
+    memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
+
+    if (!psDBPackRow(bind, values, paramCount)) {
+        psFree(bind);
+        mysql_stmt_close(stmt);
+        return -1;
+    }
+
+    if (mysql_stmt_bind_param(stmt, bind)) {
+        psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
+        mysql_rollback(dbh->mysql);
+        psFree(bind);
+        mysql_stmt_close(stmt);
+        return -1;
+    }
+
+    if (mysql_stmt_execute(stmt)) {
+        psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
+                mysql_stmt_error(stmt));
+        mysql_rollback(dbh->mysql);
+        psFree(bind);
+        mysql_stmt_close(stmt);
+        return -1;
+    }
+
+    psFree(bind);
+
+    // mysql_stmt_affected_rows() must be called before a commit
+    rowsAffected = mysql_stmt_affected_rows(stmt);
+
+    mysql_stmt_close(stmt);
+
+    return rowsAffected;
+}
+
+long psDBDeleteRows(psDB *dbh,
+                    const char *tableName,
+                    const psMetadata *where,
+                    unsigned long long limit)
+{
+    char            *query;
+    psS64           rows = 0;
+
+    // Verify database is not NULL
+    if(dbh == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
+        return -1;
+    }
+
+    // Create SQL statement string
+    query = psDBGenerateDeleteRowSQL(tableName, where,limit);
+    if (!query) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
+        return -1;
+    }
+
+    // Run SQL query
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "Delete failed.");
+        mysql_rollback(dbh->mysql);
+        psFree(query);
+        return -1;
+    }
+    psFree(query);
+
+    // Get the number of affected row for the delete command
+    rows = (psS64)mysql_affected_rows(dbh->mysql);
+
+    return rows;
+}
+
+long psDBLastInsertID(psDB *dbh)
+{
+    // XXX return type is actually my_ulonglong - should the return be psU64?
+    return (long)mysql_insert_id(dbh->mysql);
+}
+
+bool psDBExplicitTrans(psDB *dbh, bool mode)
+{
+    // Verify database is not NULL
+    if(dbh == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
+        return false;
+    }
+
+    // mode needs to be inverted as autocommits are the opposide of explicit
+    // transactions.
+    // the return value also needs to be inverted for the same reason.
+    // is it safe to assume my_bool always safely casts to bool?
+    return !(bool)mysql_autocommit(dbh->mysql, !mode);
+}
+
+bool psDBTransaction(psDB *dbh)
+{
+    // Verify database is not NULL
+    if(dbh == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
+        return false;
+    }
+
+    bool status = p_psDBRunQuery(dbh, "START TRANSACTION");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to start a new transaction.");
+    }
+
+    return status;
+}
+
+bool psDBCommit(psDB *dbh)
+{
+    // Verify database is not NULL
+    if(dbh == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
+        return false;
+    }
+
+    // is it safe to assume my_bool always safely casts to bool?
+    // mysql_commit - Zero if successful. Non-zero if an error occurred.
+    return !(bool)mysql_commit(dbh->mysql);
+}
+
+bool psDBRollback(psDB *dbh)
+{
+    // Verify database is not NULL
+    if(dbh == NULL) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
+        return false;
+    }
+
+    // is it safe to assume my_bool always safely casts to bool?
+    // mysql_rollback - Zero if successful. Non-zero if an error occurred.
+    return !(bool)mysql_rollback(dbh->mysql);
+}
+
+
+// database utility functions
+/*****************************************************************************/
+
+bool p_psDBRunQuery(psDB *dbh,
+                    const char *format,
+                    ...)
+{
+    va_list argPtr;
+    char *dest = NULL;
+
+    // Verify database object is not NULL
+    if(dbh == NULL) {
+        psError(PS_ERR_BAD_PARAMETER_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
+        return false;
+    }
+
+    // Run query
+    va_start(argPtr, format);
+    if(argPtr == NULL) {
+        dest=psStringCopy(format);
+    } else {
+        int destSize = vsnprintf(dest, 0, format, argPtr);
+        dest = psAlloc(destSize+1);
+        vsnprintf(dest, destSize+1, format, argPtr);
+    }
+    va_end(argPtr);
+    if (mysql_real_query(dbh->mysql, dest, (unsigned long)strlen(dest)) !=0) {
+        //The following if statement was added to standardize outputs between platforms for testing purposes.
+        char mysqlTemp[165];
+        strncpy(mysqlTemp,
+                "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null) WHERE' at line 1", 165);
+        if ( !strncmp(mysql_error(dbh->mysql), mysqlTemp, 145) ) {
+            psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_QUERY_FAIL, mysqlTemp);
+        } else {
+            psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_QUERY_FAIL, mysql_error(dbh->mysql));
+        }
+        psFree(dest);
+        return false;
+    }
+
+    psFree(dest);
+    return true;
+}
+
+psArray *p_psDBSFetchResult(psDB *dbh)
+{
     MYSQL_RES       *result;            // complete db result set
     MYSQL_ROW       row;                // single row of db result set
     MYSQL_FIELD     *field;             // field type info
-    char            *query;             // SQL query
     my_ulonglong    rowCount;           // number of rows in db result set
     unsigned int    fieldCount;         // number of fields in db result set
@@ -482,19 +921,4 @@
     psU32           pType;              // psElemType of a field
     psPtr           data;               // copy of result field
-
-    // Create select row query
-    query = psDBGenerateSelectRowSQL(tableName, NULL, where, limit);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
-        return NULL;
-    }
-
-    // Run SQL query
-    if (!p_psDBRunQuery(dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "Query execution failed.");
-        psFree(query);
-        return NULL;
-    }
-    psFree(query);
 
     result = mysql_store_result(dbh->mysql);
@@ -575,423 +999,4 @@
 
     return resultSet;
-}
-
-bool psDBInsertOneRow(psDB *dbh,
-                      const char *tableName,
-                      const psMetadata *row)
-{
-    psArray         *rowSet;           // psArray of row to insert
-
-    // Check for null row
-    if(row == NULL) {
-        psError(PS_ERR_UNKNOWN,true,PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
-        return false;
-    }
-
-    // Create array to store single row
-    rowSet = psArrayAlloc(1);
-    rowSet->n = 0;
-    psArrayAdd(rowSet, 0, (psPtr)row);
-
-    // Execute function to insert rows
-    if (!psDBInsertRows(dbh, tableName, rowSet)) {
-        psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
-        psFree(rowSet);
-        return false;
-    }
-
-    psFree(rowSet);
-
-    return true;
-}
-
-bool psDBInsertRows(psDB *dbh,
-                    const char *tableName,
-                    const psArray *rowSet)
-{
-    psMetadata      *row;               // row of data
-    char            *query;             // SQL query
-    MYSQL_STMT      *stmt;              // prepared db statement
-    MYSQL_BIND      *bind;              // field values to insert
-    unsigned long   paramCount;         // number of placeholders in query
-    psU64           j;                  // row index
-
-    // Verify database connections is set up
-    if(dbh == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
-        return false;
-    }
-
-    // Verify row array is non-NULL
-    if(rowSet == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INSERT_ROW_FAIL);
-        return false;
-    }
-
-    // we are assuming that all rows in the set have an identical with reguard
-    // to field count and type
-    row = rowSet->data[0];
-
-    // Generate SQL query string
-    query = psDBGenerateInsertRowSQL(tableName, row);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, PS_ERRORTEXT_psDB_QUERY_GEN_FAIL);
-        return false;
-    }
-
-    // Prepare SQL statement
-    stmt = mysql_stmt_init(dbh->mysql);
-    if (!stmt) {
-        psAbort(__func__, "mysql_stmt_init(), out of memory.");
-    }
-    if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to prepare query.  Error: %s", mysql_stmt_error(stmt));
-        mysql_stmt_close(stmt);
-        psFree(query);
-        return false;
-    }
-
-    psFree(query);
-
-    // how many place holders are in our query
-    paramCount = mysql_stmt_param_count(stmt);
-
-    // structure larger enough to hold one field of data per place holder
-    bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
-
-    // loop over rows
-    for (j = 0; j < rowSet->n; j++) {
-        row = rowSet->data[j];
-
-        // reset bind for each row
-        memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
-
-        if (!psDBPackRow(bind, row, paramCount)) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to pack params into bind structure.");
-
-            mysql_rollback(dbh->mysql);
-
-            psFree(bind);
-            mysql_stmt_close(stmt);
-        }
-
-        if (mysql_stmt_bind_param(stmt, bind)) {
-            psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
-
-            mysql_rollback(dbh->mysql);
-
-            psFree(bind);
-            mysql_stmt_close(stmt);
-
-            return false;
-        }
-
-        if (mysql_stmt_execute(stmt)) {
-            psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
-                    mysql_stmt_error(stmt));
-
-            mysql_rollback(dbh->mysql);
-
-            psFree(bind);
-            mysql_stmt_close(stmt);
-
-            return false;
-        }
-    } // end loop over rows
-
-    psFree(bind);
-    mysql_stmt_close(stmt);
-
-    return true;
-}
-
-psArray *psDBDumpRows(psDB *dbh,
-                      const char *tableName)
-{
-    return psDBSelectRows(dbh, tableName, NULL, 0);
-}
-
-psMetadata *psDBDumpCols(psDB *dbh,
-                         const char *tableName)
-{
-    MYSQL_RES       *result;
-    MYSQL_FIELD     *field;
-    unsigned int    fieldCount;
-    psMetadata      *table;
-    psU32           pType;
-    unsigned int    i;
-    psPtr           column;
-
-    // Verify database object is not null
-    if(dbh == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
-        return NULL;
-    }
-
-    // Verify table name is not null
-    if(tableName == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_NULL_TABLE);
-        return NULL;
-    }
-
-    // find column types
-    result = mysql_list_fields(dbh->mysql, tableName, NULL);
-    if (!result) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "Failed to retrieve column types.");
-    }
-
-    field = mysql_fetch_fields(result);
-    fieldCount = mysql_num_fields(result);
-
-    table = psMetadataAlloc();
-
-    // fetch each column and load into psMetadata
-    for (i =0; i < fieldCount; i++) {
-        // find ptype of column
-        pType = psDBMySQLToPType(field[i].type, field[i].flags);
-        //psLogMsg( __func__, PS_LOG_INFO, "pType=[%ld]\n", pType );
-
-        // if the ptype is PS_TYPE_PTR assume that it's a string and fetch the
-        // column as an psArray of strings; otherwise fetch the column as a
-        // psVector.
-        if (pType == PS_DATA_STRING) {
-            // PS_DATA_UNKNOWN -> PS_DATA_ARRAY ?
-            column = psDBSelectColumn(dbh, tableName, field[i].name, 0);
-            psMetadataAddArray(table, PS_LIST_TAIL, field[i].name, 0, "", column);
-            //            psMetadataAddStr(table, PS_LIST_TAIL, field[i].name, "", column);
-            psFree(column);
-        } else {
-            column = psDBSelectColumnNum(dbh, tableName, field[i].name, pType, 0);
-            psMetadataAddVector(table, PS_LIST_TAIL, field[i].name, 0, "", column);
-            psFree(column);
-        }
-    }
-
-    return table;
-}
-
-long psDBUpdateRows(psDB *dbh,
-                    const char *tableName,
-                    const psMetadata *where,
-                    const psMetadata *values)
-{
-    char            *query;
-    MYSQL_STMT      *stmt;              // prepared db statement
-    unsigned long   paramCount;         // number of placeholders in query
-    MYSQL_BIND      *bind;              // field values to insert
-    my_ulonglong    rowsAffected;       // number of rows affected by query
-
-    // Verify database object is not NULL
-    if(dbh == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
-        return -1;
-    }
-
-    // Generate SQL query to update row
-    query = psDBGenerateUpdateRowSQL(tableName, where, values);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, PS_ERRORTEXT_psDB_QUERY_GEN_FAIL);
-        return -1;
-    }
-
-    // Initialize SQL statement
-    stmt = mysql_stmt_init(dbh->mysql);
-    if (!stmt) {
-        psAbort(__func__, "mysql_stmt_init(), out of memory.");
-    }
-
-    // Prepare SQL statement
-    if (mysql_stmt_prepare(stmt, query, (unsigned long)strlen(query))) {
-        psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_PREPARE_FAIL, mysql_stmt_error(stmt));
-        mysql_stmt_close(stmt);
-        psFree(query);
-        return -1;
-    }
-    psFree(query);
-
-    // how many place holders are in our query
-    paramCount = mysql_stmt_param_count(stmt);
-
-    // structure large enough to hold one field of data per place holder
-    bind = psAlloc(sizeof(MYSQL_BIND) * paramCount);
-
-    // init bind
-    memset(bind, 0, sizeof(MYSQL_BIND) * paramCount);
-
-    if (!psDBPackRow(bind, values, paramCount)) {
-        psFree(bind);
-        mysql_stmt_close(stmt);
-        return -1;
-    }
-
-    if (mysql_stmt_bind_param(stmt, bind)) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to bind params.  Error: %s", mysql_stmt_error(stmt));
-        mysql_rollback(dbh->mysql);
-        psFree(bind);
-        mysql_stmt_close(stmt);
-        return -1;
-    }
-
-    if (mysql_stmt_execute(stmt)) {
-        psError(PS_ERR_UNKNOWN, true, "Failed to execute prepared statement.  Error: %s",
-                mysql_stmt_error(stmt));
-        mysql_rollback(dbh->mysql);
-        psFree(bind);
-        mysql_stmt_close(stmt);
-        return -1;
-    }
-
-    psFree(bind);
-
-    // mysql_stmt_affected_rows() must be called before a commit
-    rowsAffected = mysql_stmt_affected_rows(stmt);
-
-    mysql_stmt_close(stmt);
-
-    return rowsAffected;
-}
-
-long psDBDeleteRows(psDB *dbh,
-                    const char *tableName,
-                    const psMetadata *where,
-                    unsigned long long limit)
-{
-    char            *query;
-    psS64           rows = 0;
-
-    // Verify database is not NULL
-    if(dbh == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
-        return -1;
-    }
-
-    // Create SQL statement string
-    query = psDBGenerateDeleteRowSQL(tableName, where,limit);
-    if (!query) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Query generation failed.");
-        return -1;
-    }
-
-    // Run SQL query
-    if (!p_psDBRunQuery(dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "Delete failed.");
-        mysql_rollback(dbh->mysql);
-        psFree(query);
-        return -1;
-    }
-    psFree(query);
-
-    // Get the number of affected row for the delete command
-    rows = (psS64)mysql_affected_rows(dbh->mysql);
-
-    return rows;
-}
-
-long psDBLastInsertID(psDB *dbh)
-{
-    // XXX return type is actually my_ulonglong - should the return be psU64?
-    return (long)mysql_insert_id(dbh->mysql);
-}
-
-bool psDBExplicitTrans(psDB *dbh, bool mode)
-{
-    // Verify database is not NULL
-    if(dbh == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
-        return false;
-    }
-
-    // mode needs to be inverted as autocommits are the opposide of explicit
-    // transactions.
-    // the return value also needs to be inverted for the same reason.
-    // is it safe to assume my_bool always safely casts to bool?
-    return !(bool)mysql_autocommit(dbh->mysql, !mode);
-}
-
-bool psDBTransaction(psDB *dbh)
-{
-    // Verify database is not NULL
-    if(dbh == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
-        return false;
-    }
-
-    bool status = p_psDBRunQuery(dbh, "START TRANSACTION");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to start a new transaction.");
-    }
-
-    return status;
-}
-
-bool psDBCommit(psDB *dbh)
-{
-    // Verify database is not NULL
-    if(dbh == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
-        return false;
-    }
-
-    // is it safe to assume my_bool always safely casts to bool?
-    // mysql_commit - Zero if successful. Non-zero if an error occurred.
-    return !(bool)mysql_commit(dbh->mysql);
-}
-
-bool psDBRollback(psDB *dbh)
-{
-    // Verify database is not NULL
-    if(dbh == NULL) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, PS_ERRORTEXT_psDB_INVALID_PSDB);
-        return false;
-    }
-
-    // is it safe to assume my_bool always safely casts to bool?
-    // mysql_rollback - Zero if successful. Non-zero if an error occurred.
-    return !(bool)mysql_rollback(dbh->mysql);
-}
-
-
-// database utility functions
-/*****************************************************************************/
-
-bool p_psDBRunQuery(psDB *dbh,
-                    const char *format,
-                    ...)
-{
-    va_list argPtr;
-    char *dest = NULL;
-
-    // Verify database object is not NULL
-    if(dbh == NULL) {
-        psError(PS_ERR_BAD_PARAMETER_NULL,true,PS_ERRORTEXT_psDB_INVALID_PSDB);
-        return false;
-    }
-
-    // Run query
-    va_start(argPtr, format);
-    if(argPtr == NULL) {
-        dest=psStringCopy(format);
-    } else {
-        int destSize = vsnprintf(dest, 0, format, argPtr);
-        dest = psAlloc(destSize+1);
-        vsnprintf(dest, destSize+1, format, argPtr);
-    }
-    va_end(argPtr);
-    if (mysql_real_query(dbh->mysql, dest, (unsigned long)strlen(dest)) !=0) {
-        //The following if statement was added to standardize outputs between platforms for testing purposes.
-        char mysqlTemp[165];
-        strncpy(mysqlTemp,
-                "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'null) WHERE' at line 1", 165);
-        if ( !strncmp(mysql_error(dbh->mysql), mysqlTemp, 145) ) {
-            psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_QUERY_FAIL, mysqlTemp);
-        } else {
-            psError(PS_ERR_UNKNOWN, true, PS_ERRORTEXT_psDB_SQL_QUERY_FAIL, mysql_error(dbh->mysql));
-        }
-        psFree(dest);
-        return false;
-    }
-
-    psFree(dest);
-    return true;
 }
 
Index: /trunk/psLib/src/db/psDB.h
===================================================================
--- /trunk/psLib/src/db/psDB.h	(revision 7385)
+++ /trunk/psLib/src/db/psDB.h	(revision 7386)
@@ -10,6 +10,6 @@
  *  @author Joshua Hoblitt
  *
- *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-05-25 21:19:45 $
+ *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-07 03:40:43 $
  *
  *  Copyright 2005 Joshua Hoblitt, University of Hawaii
@@ -94,4 +94,15 @@
     const char *format,                ///< SQL string to execute
     ...                                ///< Arguments for name formatting and metadata item data.
+);
+
+/** Fetches the result of a SQL query
+ *
+ * This function returns the result of the most recent SQL query as a psArray
+ * of psMetadata.  Caveat emptor.
+ *
+ * @return psArray*:    A psArray of psMetadata or NULL on failure
+ */
+psArray *p_psDBFetchResult(
+    psDB *dbh                          ///< Database handle
 );
 
