/** @file  tst_psDB.c
 *
 * -*- mode: C; c-basic-indent: 4; tab-width: 8; indent-tabs-mode: nil -*-
 * vim: set cindent ts=8 sw=4 expandtab:
 *
 *  @brief Contains the tests for psDB.[ch]
 *
 *
 *  @author Aaron Culliney, MHPCC
 *
 *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2006-02-02 20:59:36 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 *
 */

#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>

#include "psTest.h"
#include "pslib_strict.h"

#define STR_1 "hello world!"
#define STR_2 "foobar"
#define S32_1 1974
#define S32_2 -18
#define F32_1 3.14159
#define F32_2 3.33
#define F64_1 2.7182818
#define F64_2 1.23456789
#define B_1 TRUE
#define B_2 FALSE

#define ERROR_TOL   0.001

#define CONST_ROW_1_STR      "randrow1"
#define CONST_ROW_1_S32      12345
#define CONST_ROW_1_F32      9876.5
#define CONST_ROW_1_F64      456.75
#define CONST_ROW_1_BOOL     TRUE

#define CONST_ROW_2_STR      "randrow2"
#define CONST_ROW_2_S32      2345
#define CONST_ROW_2_F32      876.5
#define CONST_ROW_2_F64      56.75
#define CONST_ROW_2_BOOL     FALSE

#define TAB_COL_0_NAME      "key_string"
#define TAB_COL_1_NAME      "key_s32"
#define TAB_COL_2_NAME      "key_f32"
#define TAB_COL_3_NAME      "key_f64"
#define TAB_COL_4_NAME      "key_bool"
#define TAB_COL_5_NAME      "key_s32_0"

static psDB *_init_psDB( void );
static psMetadata *_get_CreateTableMetadata( void );
static psMetadata *_get_RowMetadataValues(const char *val0, psS32 val1, psF32 val2, psF64 val3, psBool val4);
static psMetadata *_get_RowMetadata(
    const char *key0, const char *comm0, const char *val0,
    const char *key1, const char *comm1, psS32  val1,
    const char *key2, const char *comm2, psF32  val2,
    const char *key3, const char *comm3, psF64  val3,
    const char *key4, const char *comm4, psBool val4,
    const char *key5, const char *comm5, psS32  val5);
static psMetadata *_get_row( void );
static psMetadata *_get_invalid_row( void );
static psMetadata *_get_where( void );
static psMetadata *_get_invalid_where( void );
static psMetadata *_get_where_bad_value( void );
static psMetadata *_get_update_values(const char *val0, psS32 val1, psF32 val2, psF64 val3, psBool val4);
static bool _check_row(psMetadata* row);
static bool _check_row_update(psMetadata* row);
static bool _check_const_row1(psMetadata* row);
static bool _check_const_row2(psMetadata* row);

//static psS32 TPDBCreate( void );
//static psS32 TPDBDrop( void );
static psS32 TPDBInit( void );
static psS32 TPDBChange( void );
static psS32 TPDBCreateTable( void );
static psS32 TPDBDropTable( void );
static psS32 TPDBSelectColumn( void );
static psS32 TPDBSelectColumnNum( void );
static psS32 TPDBSelectRows( void );
static psS32 TPDBInsertOneRow( void );
static psS32 TPDBInsertRows( void );
static psS32 TPDBDumpRows( void );
static psS32 TPDBDumpCols( void );
static psS32 TPDBUpdateRows( void );
static psS32 TPDBDeleteRows( void );

testDescription tests[] = {
                              {TPDBInit,           841,  "dbInit",            0, false},
                              {TPDBChange,         842,  "dbChange",          0, false},
                              {TPDBCreateTable,    843,  "dbCreateTable",     0, false},
                              {TPDBDropTable,      844,  "dbDropTable",       0, false},
                              {TPDBSelectColumn,   845,  "dbSelectColumn",    0, false},
                              {TPDBSelectColumnNum,846,  "dbSelectColumnNum", 0, false},
                              {TPDBSelectRows,     847,  "dbSelectRows",      0, false},
                              {TPDBInsertOneRow,   848,  "dbInsertOneRow",    0, false},
                              {TPDBInsertRows,     849,  "dbInsertRows",      0, false},
                              {TPDBDumpRows,       850,  "dbDumpRows",        0, false},
                              {TPDBDumpCols,       851,  "dbDumpCols",        0, false},
                              {TPDBUpdateRows,     852,  "dbUpdateRows",      0, false},
                              {TPDBDeleteRows,     853,  "dbDeleteRows",      0, false},
                              //{TPDBCreate,        -14, "dbCreate",          0, false},
                              //{TPDBDrop,          -15, "dbDrop",            0, false},
                              {NULL}
                          };

static const char *host    = "localhost";
static const char *user    = "test";
static const char *passwd  = "";
static const char *dbname  = "test";

// internal method to initialize DB
psDB *_init_psDB( void )
{
    psDB *dbh = NULL;

    // Initialize database connection with test database
    dbh = psDBInit(host, user, passwd, dbname);
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN, true, "could not initialize DB connection in %s!", __func__ );
    }

    return dbh;
}

psMetadata *_get_CreateTableMetadata( void )
{
    return _get_RowMetadata(
               TAB_COL_0_NAME, "comment-string",     "90000", // value used to determine size of field
               TAB_COL_1_NAME,    "Primary Key",        0,       // values unused here ...
               TAB_COL_2_NAME,    "Key",                0.0,
               TAB_COL_3_NAME,    "",                   0.0,
               TAB_COL_4_NAME,   "",                   FALSE,
               TAB_COL_5_NAME,  "Key,AUTO_INCREMENT", 0);
}

psMetadata *_get_RowMetadataValues(const char *val0, psS32 val1, psF32 val2, psF64 val3, psBool val4)
{
    return _get_RowMetadata(
               TAB_COL_0_NAME, "comment-string", val0,
               TAB_COL_1_NAME,    "comment-s32",    val1,
               TAB_COL_2_NAME,    "comment-f32",    val2,
               TAB_COL_3_NAME,    "comment-f64",    val3,
               TAB_COL_4_NAME,   "comment-bool",   val4,
               NULL,         NULL,             0.0);
}

psMetadata *_get_RowMetadata(
    const char *key0, const char *comm0, const char *val0,
    const char *key1, const char *comm1, psS32  val1,
    const char *key2, const char *comm2, psF32  val2,
    const char *key3, const char *comm3, psF64  val3,
    const char *key4, const char *comm4, psBool val4,
    const char *key5, const char *comm5, psS32  val5)
{
    psMetadata *md = NULL;
    psMetadataItem *str=NULL, *s32_0=NULL, *s32=NULL, *f32=NULL, *f64=NULL, *b;

    md = psMetadataAlloc();
    if (md == NULL) {
        psError(PS_ERR_UNKNOWN, true, "could not create psMetadata in %s!", __func__ );
        return NULL;
    }
    if (key0 != NULL) {
        str = psMetadataItemAllocStr(key0, comm0, val0);
    }
    if (key5 != NULL) {
        s32_0 = psMetadataItemAllocS32(key5, comm5, val5);
    }
    s32 = psMetadataItemAllocS32 (key1, comm1, val1);
    f32 = psMetadataItemAllocF32 (key2, comm2, val2);
    f64 = psMetadataItemAllocF64 (key3, comm3, val3);
    b   = psMetadataItemAllocBool(key4, comm4, val4);

    if ( ((key0 != NULL) && (str == NULL)) || (s32 == NULL) || (f32 == NULL) || (f64 == NULL) || (b == NULL) ||
            ((key5 != NULL) && (s32_0 == NULL)) ) {
        psError(PS_ERR_UNKNOWN, true, "could not create psMetadataItem(s) in %s!", __func__ );
        return NULL;
    }
    if ( ((key0 != NULL) && !psMetadataAddItem(md, str, 0, 0)) ||
            !psMetadataAddItem(md, s32, 0, 0) || !psMetadataAddItem(md, f32, 0, 0) ||
            !psMetadataAddItem(md, f64, 0, 0) || !psMetadataAddItem(md, b,   0, 0) ||
            ((key5 != NULL) && !psMetadataAddItem(md, s32_0, 0, 0))) {
        psError(PS_ERR_UNKNOWN, true, "could not add psMetadataItem(s) to psMetadata in %s!", __func__ );
        return NULL;
    }

    if (str != NULL) {
        psFree(str);
    }
    psFree(s32);
    psFree(f32);
    psFree(f64);
    psFree(b);
    if (s32_0 != NULL) {
        psFree(s32_0);
    }

    return md;
}

psMetadata *_get_const_row1( void )
{
    char buf[32];
    snprintf(buf, 32, "%s", CONST_ROW_1_STR );
    return _get_RowMetadata(
               TAB_COL_0_NAME, "comment-string", buf,
               TAB_COL_1_NAME,    "comment-s32",    CONST_ROW_1_S32,
               TAB_COL_2_NAME,    "comment-f32",    CONST_ROW_1_F32,
               TAB_COL_3_NAME,    "comment-f64",    CONST_ROW_1_F64,
               TAB_COL_4_NAME,   "comment-bool",   CONST_ROW_1_BOOL,
               NULL,         NULL,             0.0);
}

psMetadata *_get_const_row2( void )
{
    char buf[32];
    snprintf(buf, 32, "%s",CONST_ROW_2_STR);
    return _get_RowMetadata(
               TAB_COL_0_NAME, "comment-string", buf,
               TAB_COL_1_NAME,    "comment-s32",    CONST_ROW_2_S32,
               TAB_COL_2_NAME,    "comment-f32",    CONST_ROW_2_F32,
               TAB_COL_3_NAME,    "comment-f64",    CONST_ROW_2_F64,
               TAB_COL_4_NAME,   "comment-bool",   CONST_ROW_2_BOOL,
               NULL,         NULL,             0.0);
}

psMetadata *_get_row( void )
{
    return _get_RowMetadata(
               TAB_COL_0_NAME, "comment-string", STR_1,
               TAB_COL_1_NAME,    "comment-s32",    S32_1,
               TAB_COL_2_NAME,    "comment-f32",    F32_1,
               TAB_COL_3_NAME,    "comment-f64",    F64_1,
               TAB_COL_4_NAME,   "comment-bool",   B_1,
               NULL,         NULL,             0.0);
}

psMetadata *_get_invalid_row( void )
{
    return _get_RowMetadata(
               TAB_COL_0_NAME, "comment-string", STR_1,
               TAB_COL_1_NAME,    "comment-s32",    S32_1,
               "key_999",    "comment-f32",    F32_1,
               TAB_COL_3_NAME,    "comment-f64",    F64_1,
               TAB_COL_4_NAME,   "comment-bool",   B_1,
               NULL,         NULL,             0.0);
}

psMetadata *_get_where( void )
{
    psMetadata *md = NULL;
    psMetadataItem *s32=NULL;

    md = psMetadataAlloc();
    if (md == NULL) {
        psError(PS_ERR_UNKNOWN, true, "could not create psMetadata in %s!", __func__ );
        return NULL;
    }
    s32 = psMetadataItemAllocS32(TAB_COL_1_NAME, "", S32_1);
    if (s32 == NULL) {
        psError(PS_ERR_UNKNOWN, true, "could not create psMetadataItem in %s!", __func__ );
        return NULL;
    }
    if (!psMetadataAddItem(md, s32, 0, 0)) {
        psError(PS_ERR_UNKNOWN, true, "could not add psMetadataItem(s) to psMetadata in %s!", __func__ );
        return NULL;
    }

    psFree(s32);
    return md;
}

psMetadata *_get_invalid_where( void )
{
    psMetadata *md = NULL;
    psMetadataItem *s32=NULL;

    md = psMetadataAlloc();
    if (md == NULL) {
        psError(PS_ERR_UNKNOWN, true, "could not create psMetadata in %s!", __func__ );
        return NULL;
    }
    s32 = psMetadataItemAllocS32("col999", "", S32_1);
    if (s32 == NULL) {
        psError(PS_ERR_UNKNOWN, true, "could not create psMetadataItem in %s!", __func__ );
        return NULL;
    }
    if (!psMetadataAddItem(md, s32, 0, 0)) {
        psError(PS_ERR_UNKNOWN, true, "could not add psMetadataItem(s) to psMetadata in %s!", __func__ );
        return NULL;
    }

    psFree(s32);
    return md;
}

psMetadata *_get_where_bad_value( void )
{
    psMetadata *md = NULL;
    psMetadataItem *s32=NULL;

    md = psMetadataAlloc();
    if (md == NULL) {
        psError(PS_ERR_UNKNOWN, true, "could not create psMetadata in %s!", __func__ );
        return NULL;
    }
    s32 = psMetadataItemAllocS32(TAB_COL_1_NAME, "", S32_1 + 1);
    if (s32 == NULL) {
        psError(PS_ERR_UNKNOWN, true, "could not create psMetadataItem in %s!", __func__ );
        return NULL;
    }
    if (!psMetadataAddItem(md, s32, 0, 0)) {
        psError(PS_ERR_UNKNOWN, true, "could not add psMetadataItem(s) to psMetadata in %s!", __func__ );
        return NULL;
    }

    psFree(s32);
    return md;
}

psMetadata *_get_update_values(const char *val0, psS32 val1, psF32 val2, psF64 val3, psBool val4)
{
    return _get_RowMetadataValues(val0, val1, val2, val3, val4);
}

bool _check_row(psMetadata* row)
{
    bool              returnValue = true;
    psMetadataItem*   item        = NULL;

    item = psMetadataLookup(row,TAB_COL_0_NAME);
    if((item==NULL) || (strcmp(item->data.V,STR_1)!=0)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_string item %s not as expected %s",
                item->data.V,STR_1);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_1_NAME);
    if((item==NULL) || (item->data.S32 != S32_1)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_s32 item %d not as expected %d",
                item->data.S32, S32_1);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_2_NAME);
    if((item==NULL) || (fabs(item->data.F32-F32_1)>ERROR_TOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_f32 item %f not as expected %f",
                item->data.F32, F32_1);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_3_NAME);
    if((item==NULL) || (fabs(item->data.F64-F64_1)>ERROR_TOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_f64 item %lf not as expected %lf",
                item->data.F64,F64_1);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_4_NAME);
    if((item==NULL) || (item->data.B != B_1)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_bool item %d not as expected %d",
                item->data.B, B_1);
        return false;
    }

    return returnValue;
}

bool _check_row_update(psMetadata* row)
{
    bool              returnValue = true;
    psMetadataItem*   item        = NULL;

    item = psMetadataLookup(row,TAB_COL_0_NAME);
    if((item==NULL) || (strcmp(item->data.V,STR_2)!=0)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_string item %s not as expected %s",
                item->data.V,STR_2);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_1_NAME);
    if((item==NULL) || (item->data.S32 != S32_2)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_s32 item %d not as expected %d",
                item->data.S32, S32_2);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_2_NAME);
    if((item==NULL) || (fabs(item->data.F32-F32_2)>ERROR_TOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_f32 item %f not as expected %f",
                item->data.F32, F32_2);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_3_NAME);
    if((item==NULL) || (fabs(item->data.F64-F64_2)>ERROR_TOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_f64 item %lf not as expected %lf",
                item->data.F64,F64_2);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_4_NAME);
    if((item==NULL) || (item->data.B != B_2)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_bool item %d not as expected %d",
                item->data.B, B_2);
        return false;
    }

    return returnValue;
}

bool _check_const_row1(psMetadata* row)
{
    bool              returnValue = true;
    psMetadataItem*   item        = NULL;

    item = psMetadataLookup(row,TAB_COL_0_NAME);
    if((item==NULL) || (strcmp(item->data.V,CONST_ROW_1_STR)!=0)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_string item %s not as expected %s",
                item->data.V,CONST_ROW_1_STR);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_1_NAME);
    if((item==NULL) || (item->data.S32 != CONST_ROW_1_S32)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_s32 item %d not as expected %d",
                item->data.S32, CONST_ROW_1_S32);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_2_NAME);
    if((item==NULL) || (fabs(item->data.F32-CONST_ROW_1_F32)>ERROR_TOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_f32 item %f not as expected %f",
                item->data.F32, CONST_ROW_1_F32);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_3_NAME);
    if((item==NULL) || (fabs(item->data.F64-CONST_ROW_1_F64)>ERROR_TOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_f64 item %lf not as expected %lf",
                item->data.F64,CONST_ROW_1_F64);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_4_NAME);
    if((item==NULL) || (item->data.B != CONST_ROW_1_BOOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_bool item %d not as expected %d",
                item->data.B, CONST_ROW_1_BOOL);
        return false;
    }

    return returnValue;
}

bool _check_const_row2(psMetadata* row)
{
    bool              returnValue = true;
    psMetadataItem*   item        = NULL;

    item = psMetadataLookup(row,TAB_COL_0_NAME);
    if((item==NULL) || (strcmp(item->data.V,CONST_ROW_2_STR)!=0)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_string item %s not as expected %s",
                item->data.V,CONST_ROW_2_STR);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_1_NAME);
    if((item==NULL) || (item->data.S32 != CONST_ROW_2_S32)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_s32 item %d not as expected %d",
                item->data.S32, CONST_ROW_2_S32);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_2_NAME);
    if((item==NULL) || (fabs(item->data.F32-CONST_ROW_2_F32)>ERROR_TOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_f32 item %f not as expected %f",
                item->data.F32, CONST_ROW_2_F32);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_3_NAME);
    if((item==NULL) || (fabs(item->data.F64-CONST_ROW_2_F64)>ERROR_TOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_f64 item %lf not as expected %lf",
                item->data.F64,CONST_ROW_2_F64);
        return false;
    }

    item = psMetadataLookup(row,TAB_COL_4_NAME);
    if((item==NULL) || (item->data.B != CONST_ROW_2_BOOL)) {
        psError(PS_ERR_UNKNOWN,true,"Column key_bool item %d not as expected %d",
                item->data.B, CONST_ROW_2_BOOL);
        return false;
    }

    return returnValue;
}

psS32 main(psS32 argc, char* argv[])
{
    psLogSetLevel( PS_LOG_INFO );

    srand(time(NULL));

    return ( ! runTestSuite( stderr, "psDB", tests, argc, argv ) );
}

// Testpoint #841, initialize/break-down MySQL connection.
psS32 TPDBInit( void )
{
    psDB *dbh = NULL;

    // Initialize database with valid arguments
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL to be returned for valid arguments");
        return 1;
    }

    // Cleanup database/connection with valid psDB object
    psDBCleanup(dbh);

    // Attempt to initialize database with invalid arguments
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid host");
    dbh = psDBInit("xxx",NULL,NULL,NULL);
    if(dbh != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL psDB with invalid arguments");
        return 2;
    }

    // Attempt cleanup database/connection with NULL psDB object
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database objec");
    psDBCleanup(NULL);

    return 0;
}

// Testpoint #842, psDBChange shall change databases.
psS32 TPDBChange( void )
{
    psDB *dbh = NULL;

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL for valid arguments");
        return 1;
    }

    // Attempt to change database with valid arguments
    if(!psDBChange(dbh, dbname)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for valid arguments");
        return 2;
    }

    // Attemp to change database to invalid database name
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid database");
    if(psDBChange(dbh,"abc")) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return true for unknown database name");
        return 3;
    }

    // Cleanup database connection
    psDBCleanup(dbh);

    // Attempt to change database with NULL database object
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for null database object");
    if(psDBChange(NULL,dbname)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return true for NULL database object");
        return 4;
    }

    return 0;
}

// Testpoint #843, psDBCreateTable shall create tables in the test database ...
psS32 TPDBCreateTable( void )
{
    psDB *dbh = NULL;
    const char* table = "table1";

    // Create metadata for table definition
    psMetadata *md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL for valid argument in database connection");
        return 1;
    }

    // Attempt to create database table with valid arguments
    if(!psDBCreateTable(dbh, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for valid arguments");
        return 2;
    } else {
        // Drop the table from the test database
        psDBDropTable(dbh, table);
    }

    // Free metadata definition of table
    psFree(md);

    // Attempt to create table with NULL table definition
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL parameter");
    if(psDBCreateTable(dbh,table,NULL)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return of true for NULL metadata object");
        return 3;
    }

    // Attempt to create table with NULL connection
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL parameter");
    if(psDBCreateTable(NULL, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return of true for NULL database object");
        return 4;
    }

    // Close/cleanup database connection
    psDBCleanup(dbh);

    return 0;
}

// Testpoint #844, psDBDropTable shall remove tables in the test database ...
psS32 TPDBDropTable( void )
{
    psDB *dbh = NULL;
    const char* table = "table2";

    // Create table definition metadata
    psMetadata *row=NULL, *md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return to initialize database");
        return 1;
    }

    // Create table in database
    if(psDBCreateTable(dbh, table, md)) {

        // Drop table with valid arguments
        if(!psDBDropTable(dbh, table)) {
            psError(PS_ERR_UNKNOWN,true,"Did not expect return false for valid arguments");
            return 2;
        }

        // insert should fail since the table has been drop from database
        psLogMsg( __func__, PS_LOG_INFO, "psDBDropTable: insert should fail here...\n" );
        row = _get_row();
        if (psDBInsertOneRow(dbh, table, row)) {
            psError(PS_ERR_UNKNOWN,true,"Did not expect to successfully insert row into dropped table");
            return 3;
        }
        psFree(row);
    } else {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false to create table");
        return 4;
    }

    // Attempt to drop table from NULL psDB object
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL database object");
    if(psDBDropTable(NULL,table)) {
        psError(PS_ERR_UNKNOWN,true,"Did not return false as expected for NULL database object");
        return 5;
    }

    // Attempt to drop table from valid psDB but invalid table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid table");
    if(psDBDropTable(dbh,"table99")) {
        psError(PS_ERR_UNKNOWN,true,"Did not return false as expected for invalid table");
        return 6;
    }

    // Attempt to drop table from valid psDB but NULL table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL table");
    if(psDBDropTable(dbh,NULL)) {
        psError(PS_ERR_UNKNOWN,true,"Did not return false as expected for NULL table");
        return 7;
    }

    psFree(md);
    psDBCleanup(dbh);

    return 0;
}

// Testpoint #845, TPDBSelectColumn shall write/select a column from a test table ...
psS32 TPDBSelectColumn( void )
{
    psDB *dbh = NULL;
    const char* table = "table3";
    psArray *ary = NULL;
    char *ptr=NULL;

    // Create table definition metadata
    psMetadata *row=NULL, *md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL to initialize database connection");
        return 1;
    }

    // Create database table
    if(!psDBCreateTable(dbh,table,md)) {
        psError(PS_ERR_UNKNOWN,true,"Unable to create database table for testing");
        psDBCleanup(dbh);
        return 2;
    }

    // Insert known constant row #1
    row = _get_const_row1();
    if(!psDBInsertOneRow(dbh, table, row)) {
        psError(PS_ERR_UNKNOWN,true,"Unable to add rows to test database");
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 3;
    }
    psFree(row);

    // Insert known constant row #2
    row = _get_const_row2();
    if(!psDBInsertOneRow(dbh, table, row)) {
        psError(PS_ERR_UNKNOWN,true,"Unable to add rows to test database");
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 4;
    }
    psFree(row);

    // Insert known row
    row = _get_row();
    if(!psDBInsertOneRow(dbh, table, row)) {
        psError(PS_ERR_UNKNOWN,true,"Unable to add rows to test database");
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 5;
    }
    psFree(row);

    // Select all items in column key_string with valid arguments
    ary = psDBSelectColumn(dbh, table, TAB_COL_0_NAME, 0);
    if (ary == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return value of NULL");
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 6;
    }

    // Verify array contents
    if(ary->n != 3) {
        psError(PS_ERR_UNKNOWN,true,"Array number of items %d not equal to expected %d",
                ary->n, 3);
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 60;
    }
    ptr = psArrayGet(ary, 2);
    if (strcmp(ptr, CONST_ROW_1_STR)) {
        psError(PS_ERR_UNKNOWN,true,"key_str column entry[%d] = %s not as expected %s",
                2,CONST_ROW_1_STR,ptr);
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 7;
    }
    psFree(ptr);
    ptr = psArrayGet(ary, 1);
    if (strcmp(ptr, CONST_ROW_2_STR)) {
        psError(PS_ERR_UNKNOWN,true,"key_str column entry[%d] = %s not as expected %s",
                1,CONST_ROW_2_STR,ptr);
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 8;
    }
    psFree(ptr);
    ptr = psArrayGet(ary, 0);
    if (strcmp(ptr, STR_1)) {
        psError(PS_ERR_UNKNOWN,true,"key_str column entry[%d] = %s not as expected %s",
                0,STR_1,ptr);
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 9;
    }
    psFree(ptr);
    psFree(ary);

    // Select items in column key_bool with limit 10 and valid arguments
    ary = psDBSelectColumn(dbh, table, TAB_COL_4_NAME, 10);
    if (ary == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return value of NULL");
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 10;
    }

    // Verify array contents
    if(ary->n != 3) {
        psError(PS_ERR_UNKNOWN,true,"Array number of items %d not equal to expected %d",
                ary->n, 3);
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 100;
    }
    ptr = psArrayGet(ary, 2);
    if(atoi(ptr) != CONST_ROW_1_BOOL) {
        psError(PS_ERR_UNKNOWN,true,"key_bool column entry[%d] = %d not as expected %d",
                2,CONST_ROW_1_BOOL,atoi(ptr));
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 11;
    }
    psFree(ptr);
    ptr = psArrayGet(ary, 1);
    if(atoi(ptr) != CONST_ROW_2_BOOL) {
        psError(PS_ERR_UNKNOWN,true,"key_bool column entry[%d] = %d not as expected %d",
                1,CONST_ROW_2_BOOL,atoi(ptr));
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 12;
    }
    psFree(ptr);
    ptr = psArrayGet(ary, 0);
    if(atoi(ptr) != B_1) {
        psError(PS_ERR_UNKNOWN,true,"key_bool column entry[%d] = %d not as expected %d",
                0,B_1,atoi(ptr));
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 13;
    }
    psFree(ptr);
    psFree(ary);

    // Attempt to select columns from NULL database object
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database");
    if(psDBSelectColumn(NULL,table,"key_str",10) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for selecting from NULL database");
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 14;
    }

    // Attempt to select column from NULL table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL table");
    if(psDBSelectColumn(dbh,NULL,"key_str",10) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for NULL table");
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 15;
    }

    // Attempt to select column from invalid table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid table");
    if(psDBSelectColumn(dbh,"table99","key_str",10) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for invalid table");
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 16;
    }

    // Attempt to select invalid column from valid database object and valid table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid column");
    if(psDBSelectColumn(dbh,table,"key_null",10) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for invalid column");
        psDBDropTable(dbh, table);
        psDBCleanup(dbh);
        return 17;
    }

    // Clean up table and memory
    psDBDropTable(dbh, table);
    psFree(md);
    psDBCleanup(dbh);

    return 0;
}

// Testpoint #846, TPDBSelectColumnNum shall write/select a column from a test table ...
psS32 TPDBSelectColumnNum( void )
{
    psDB *dbh = NULL;
    const char* table = "table4";
    psVector *vec = NULL;

    // Create table definition metadata
    psMetadata *row=NULL, *md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expected NULL return to initialize database");
        return 1;
    }

    // Create database table for test
    if(!psDBCreateTable(dbh, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for create table");
        return 2;
    }

    // Initialize database table with known rows
    row = _get_const_row1();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    row = _get_const_row2();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    row = _get_row();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    // Use valid arguments to select column with numeric values to return vector
    vec = psDBSelectColumnNum(dbh, table, TAB_COL_1_NAME, PS_TYPE_S32, 0);

    // Verify vector returned
    if (vec == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return with valid arguments");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 3;
    }
    // Verify vector values
    if(vec->n != 3) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return vector size not equal to 3");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 30;
    }
    if(vec->type.type != PS_TYPE_S32) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return vector type not equal to PS_TYPE_S32");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 31;
    }
    if ((vec->data.S32)[0] != S32_1) {
        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
                0,vec->data.S32[0], S32_1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 4;
    }
    if ((vec->data.S32)[1] != CONST_ROW_2_S32) {
        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
                1,vec->data.S32[1], CONST_ROW_2_S32);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 5;
    }
    if ((vec->data.S32)[2] != CONST_ROW_1_S32) {
        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
                2,vec->data.S32[2], CONST_ROW_1_S32);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 6;
    }
    psFree(vec);

    // Use valid arguments to select column with numeric values to return vector
    vec = psDBSelectColumnNum(dbh, table, TAB_COL_4_NAME, PS_TYPE_BOOL, 0);

    // Verify vector returned
    if (vec == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return with valid arguments");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 7;
    }
    // Verify vector values
    if(vec->n != 3) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return vector size not equal to 3");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 8;
    }
    if(vec->type.type != PS_TYPE_BOOL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return vector type not equal to PS_TYPE_BOOL");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 9;
    }
    if ((vec->data.U8)[0] != B_1) {
        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
                0,vec->data.U8[0],B_1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 10;
    }
    if ((vec->data.U8)[1] != CONST_ROW_2_BOOL) {
        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
                0,vec->data.U8[0],CONST_ROW_2_BOOL);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 11;
    }
    if ((vec->data.U8)[2] != CONST_ROW_1_BOOL) {
        psError(PS_ERR_UNKNOWN,true,"vector value[%d] = %d not as expected %d",
                0,vec->data.U8[0],CONST_ROW_1_BOOL);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 12;
    }
    psFree(vec);

    // Attempt to select columns from NULL database
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for NULL database object");
    if(psDBSelectColumnNum(NULL,table,TAB_COL_4_NAME,PS_TYPE_BOOL,10) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return with NULL database object");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 13;
    }

    // Attempt to select columns from NULL table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for NULL table");
    if(psDBSelectColumnNum(dbh,NULL,TAB_COL_4_NAME,PS_TYPE_BOOL,10) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return with NULL table");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 14;
    }

    // Attempt to select columns from invalid column
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for invalid column");
    if(psDBSelectColumnNum(dbh,table,"key_999",PS_TYPE_BOOL,10) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return with NULL column");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 15;
    }

    // Attempt to select columns from invalid column
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error for invalid type");
    if(psDBSelectColumnNum(dbh,table,TAB_COL_0_NAME,0,10) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return with invalid type");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 16;
    }

    psDBDropTable(dbh, table);
    psFree(md);
    psDBCleanup(dbh);

    return 0;
}

// Testpoint #847, TPDBSelectRows shall write/select data from a test table ...
psS32 TPDBSelectRows( void )
{
    int i;
    psDB *dbh = NULL;
    const char* table = "table5";
    psArray *ary=NULL, *ary1=NULL, *ary2=NULL;
    psMetadataItem *item = NULL;

    // Create database table definition
    psMetadata *where=NULL, *row=NULL, *md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expected NULL return to initialize database");
        return 1;
    }

    psDBDropTable(dbh,table);
    // Create database table for test
    if(!psDBCreateTable(dbh, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for create table");
        psDBCleanup(dbh);
        return 2;
    }

    // Initialize database table with known rows
    row = _get_const_row1();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    row = _get_const_row2();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    row = _get_row();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    // Generate valid where clause
    where = _get_where();

    // Select rows with non limit
    ary1 = psDBSelectRows(dbh, table, where, 0);

    // Select rows with a limit
    ary2 = psDBSelectRows(dbh, table, where, 1);
    psFree(where);

    // Cycle through both arrays to verify results
    for (i=0; i<2; i++) {
        ary = i ? ary2 : ary1;

        // Verify return array not NULL
        if (ary == NULL) {
            psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL");
            psDBDropTable(dbh,table);
            psDBCleanup(dbh);
            return 1;
        }

        if(ary->n != 1) {
            psError(PS_ERR_UNKNOWN,true,"Number of rows %d not as expected %d",
                    ary->n, 1);
            psDBDropTable(dbh,table);
            psDBCleanup(dbh);
            return 2;
        }

        // Get metadata which contains row from array
        row = (psMetadata*)psArrayGet(ary, 0);

        // Get key_s32 item from metadata
        item = psMetadataLookup(row, TAB_COL_1_NAME);
        if (item == NULL) {
            psError(PS_ERR_UNKNOWN,true,"Could not find key_s32 item in row metadata");
            psDBDropTable(dbh,table);
            psDBCleanup(dbh);
            return 2;
        }
        if (item->data.S32 != S32_1) {
            psError(PS_ERR_UNKNOWN,true,"Row item %d not as expected %d",
                    item->data.S32,S32_1);
            psDBDropTable(dbh,table);
            psDBCleanup(dbh);
            return 3;
        }

        // Get key_bool item from metadata
        item = psMetadataLookup(row, TAB_COL_4_NAME);
        if (item == NULL) {
            psError(PS_ERR_UNKNOWN,true,"Could not find key_bool item in row metadata");
            psDBDropTable(dbh,table);
            psDBCleanup(dbh);
            return 2;
        }
        if (item->data.B != B_1) {
            psError(PS_ERR_UNKNOWN,true,"Row item %d not as expected %d",
                    item->data.S32,S32_1);
            psDBDropTable(dbh,table);
            psDBCleanup(dbh);
            return 4;
        }
        psFree(ary);
        psFree(row);
    }

    // Attempt to select rows with NULL database object
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL database object");
    if(psDBSelectRows(NULL, table, where, 0) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for NULL database object");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 5;
    }

    // Attempt to select rows with invalid table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid table");
    if(psDBSelectRows(dbh, NULL, where, 0) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL return for NULL database object");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 5;
    }

    // Select rows with no where specified
    ary1 = psDBSelectRows(dbh, table, NULL, 0);
    if(ary1 == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return using NULL where");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 6;
    }
    if(ary1->n != 3) {
        psError(PS_ERR_UNKNOWN,true,"Rows return %d not as expected %d",
                ary->n,3);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 7;
    }
    psFree(ary1);

    psDBDropTable(dbh, table);
    psFree(md);
    psDBCleanup(dbh);

    return 0;
}

// Testpoint #848, TPDBInsertOneRow shall write a row of data into a test table ...
psS32 TPDBInsertOneRow( void )
{
    psDB *dbh = NULL;
    const char* table = "table6";
    psMetadata *invalidRow = NULL;
    psArray*    ary = NULL;

    // Create table definition metadata
    psMetadata *row=NULL, *md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for database initialization");
        return 1;
    }

    // Create database table
    if(!psDBCreateTable(dbh, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for create database");
        psDBCleanup(dbh);
        return 2;
    }

    // Insert a single row with valid arguments
    row = _get_const_row1();
    if(!psDBInsertOneRow(dbh, table, row)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for inserting row w/ valid arguments");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 3;
    }
    // Verify row was added to table
    ary = psDBSelectRows(dbh,table,NULL,0);
    if(ary->n != 1) {
        psError(PS_ERR_UNKNOWN,true,"Number of rows %d not as expected %d",
                ary->n,1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 30;
    }
    psFree(ary);

    // Insert a single row with NULL database
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database");
    if(psDBInsertOneRow(NULL,table,row)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for NULL database");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 4;
    }

    // Insert a single row which has column which does not match table
    invalidRow = _get_invalid_row();
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid column item");
    if(psDBInsertOneRow(dbh,table,invalidRow)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for invalid column item");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 6;
    }

    // Insert a single row with invalid table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid table");
    if(psDBInsertOneRow(dbh,"table999",row)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for invalid table");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 5;
    }

    // Insert a single row with NULL row
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL row");
    if(psDBInsertOneRow(dbh,table,NULL)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for NULL row");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 6;
    }

    psFree(row);
    psFree(invalidRow);
    psDBDropTable(dbh, table);
    psFree(md);
    psDBCleanup(dbh);

    return 0;
}

// Testpoint #849, TPDBInsertRows shall write rows of data into a test table ...
psS32 TPDBInsertRows( void )
{
    psDB *dbh = NULL;
    const char* table = "table7";
    psArray *rowSet = NULL;
    psArray* dumpRowSet = NULL;
    psMetadataItem *item=NULL;
    psArray* ary = NULL;
    psMetadata* invalidRow = NULL;
    psArray* invalidRowSet = NULL;

    //Create database table definition metadata
    psMetadata *row=NULL, *md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL for initializing database connection");
        return 1;
    }

    // Create database table for testing
    if(!psDBCreateTable(dbh, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for creating table");
        psDBCleanup(dbh);
        return 2;
    }

    // Create array of row elements
    rowSet = psArrayAlloc(3);
    rowSet->n = 0;

    row = _get_const_row1();
    psArrayAdd(rowSet, 0, row);
    psFree(row);

    row = _get_const_row2();
    psArrayAdd(rowSet, 0, row);
    psFree(row);

    row = _get_row();
    psArrayAdd(rowSet, 0, row);
    psFree(row);

    // Insert rows with valid arguments
    if(!psDBInsertRows(dbh, table, rowSet)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for inserting rows w/ valid args");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 3;
    }

    // Verify row was added to table
    ary = psDBSelectRows(dbh,table,NULL,0);
    if(ary->n != 3) {
        psError(PS_ERR_UNKNOWN,true,"Number of rows %d not as expected %d",
                ary->n,3);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 30;
    }
    psFree(ary);

    // extra checks ...
    dumpRowSet = psDBDumpRows(dbh, table);
    if (dumpRowSet == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL from dump rows");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 4;
    }

    // Get first row from array
    row = (psMetadata*)psArrayGet(dumpRowSet, 0);
    // Verify contents for column key_s32
    item = psMetadataLookup(row, TAB_COL_1_NAME);
    if ((item == NULL) || (item->data.S32 != S32_1)) {
        psError(PS_ERR_UNKNOWN,true,"Column value %d not as expected %d",
                item->data.S32, S32_1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 5;
    }
    // Verify contents for column key_bool
    item = psMetadataLookup(row, TAB_COL_4_NAME);
    if ((item == NULL) || (item->data.B != B_1)) {
        psError(PS_ERR_UNKNOWN,true,"Column value %d not as expected %d",
                item->data.B, B_1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 6;
    }
    psFree(dumpRowSet);
    psFree(row);

    // Insert rows with NULL database object
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL database");
    if(psDBInsertRows(NULL,table,rowSet)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for NULL database");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 7;
    }

    // Insert rows with NULL table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL table");
    if(psDBInsertRows(dbh,NULL,rowSet)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for NULL table");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 70;
    }

    // Insert rows with invalid table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid table");
    if(psDBInsertRows(dbh,"table999",rowSet)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for invalid table");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 8;
    }

    // Insert rows with NULL array of rows to be inserted
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL row array");
    if(psDBInsertRows(dbh,table,NULL)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false for NULL row array");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 9;
    }

    // Insert a single row which has column which does not match table
    invalidRow = _get_invalid_row();
    // Create array of invalid row element
    invalidRowSet = psArrayAlloc(1);
    invalidRowSet->n = 0;
    psArrayAdd(invalidRowSet, 0, invalidRow);
    psFree(invalidRow);

    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid column item");
    if(psDBInsertRows(dbh,table,invalidRowSet)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return value true for invalid column item");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 10;
    }
    psFree(invalidRowSet);

    psFree(rowSet);
    psDBDropTable(dbh, table);
    psFree(md);
    psDBCleanup(dbh);

    return 0;
}

// Testpoint #850, TPDBDumpRows shall dump all rows from a test table ...
psS32 TPDBDumpRows( void )
{
    psDB *dbh = NULL;
    const char* table = "table8";
    psArray *ary = NULL;

    // Create table definition metadata
    psMetadata *row=NULL, *md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL from initializing database");
        return 1;
    }

    // Create table for testing
    if(!psDBCreateTable(dbh, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false from creating table");
        psDBCleanup(dbh);
        return 2;
    }

    // Insert known data rows into table
    row = _get_const_row1();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    row = _get_const_row2();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    row = _get_row();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    // Dump row with valid parameters
    ary = psDBDumpRows(dbh, table);
    if (ary == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for dump rows");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 3;
    }
    if(ary->n != 3) {
        psError(PS_ERR_UNKNOWN,true,"Rows dumped %d not as expected %d",
                ary->n, 3);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 4;
    }

    row = (psMetadata*)psArrayGet(ary, 0);
    if(!_check_row(row)) {
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 5;
    }
    psFree(row);
    row = (psMetadata*)psArrayGet(ary, 1);
    if(!_check_const_row2(row)) {
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 6;
    }
    psFree(row);
    row = (psMetadata*)psArrayGet(ary, 2);
    if(!_check_const_row1(row)) {
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 7;
    }
    psFree(row);
    psFree(ary);

    // Attempt to dump row with database NULL
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database");
    if(psDBDumpRows(NULL,table)!=NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return non-NULL for NULL database specified");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 8;
    }

    // Attempt to dump row with table NULL
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL table");
    if(psDBDumpRows(dbh,NULL)!=NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return non-NULL for NULL table specified");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 9;
    }

    psDBDropTable(dbh, table);

    psFree(md);
    psDBCleanup(dbh);

    return 0;
}

// Testpoint #851, TPDBDumpCols shall dump all cols from a test table ...
psS32 TPDBDumpCols( void )
{
    psDB*                dbh     = NULL;
    const char*          table   = "table9";
    psMetadata*          row     = NULL;
    psMetadata*          meta    = NULL;
    psMetadata*          md      = NULL;
    psMetadataIterator*  mdIter  = NULL;
    psMetadataItem*      mdItem  = NULL;
    int                  itemNum = 0;

    // Create database table definition
    md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return to initialize database");
        return 1;
    }

    // Create database table for testing
    if(!psDBCreateTable(dbh, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return of false to create test table");
        psDBCleanup(dbh);
        return 2;
    }

    // Add row with known data values
    row = _get_const_row1();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    row = _get_const_row2();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    row = _get_row();
    psDBInsertOneRow(dbh, table, row);
    psFree(row);

    // Dump columns with valid arguments
    meta = psDBDumpCols(dbh, table);
    mdIter = psMetadataIteratorAlloc(meta,PS_LIST_HEAD,NULL);

    // Verify contents of metadata returned
    if (meta == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return value NULL for dumpCols with valid args");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 3;
    }
    if(meta->list->n != 6) {
        psError(PS_ERR_UNKNOWN,true,"Number of cols = %d not as expected %d",
                meta->list->n,6);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 4;
    }
    // Verify the metadata items
    itemNum = 0;
    while ((mdItem = psMetadataGetAndIncrement(mdIter)) != NULL) {
        switch(itemNum) {
        case 0:
            if(mdItem->type != PS_DATA_VECTOR) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
                        itemNum,mdItem->type,PS_DATA_VECTOR);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 5*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_S32) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_S32);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 6*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->n != 3) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->n,3);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 7*(itemNum+1);
            }
            if(strcmp(mdItem->name,TAB_COL_5_NAME) != 0) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
                        itemNum,mdItem->name,TAB_COL_5_NAME);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 8*(itemNum+1);
            }
            break;
        case 1:
            if(mdItem->type != PS_DATA_VECTOR) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
                        itemNum,mdItem->type,PS_DATA_VECTOR);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 5*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_BOOL) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_BOOL);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 6*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->n != 3) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->n,3);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 7*(itemNum+1);
            }
            if(strcmp(mdItem->name,TAB_COL_4_NAME) != 0) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
                        itemNum,mdItem->name,TAB_COL_4_NAME);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 8*(itemNum+1);
            }
            break;
        case 2:
            if(mdItem->type != PS_DATA_VECTOR) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
                        itemNum,mdItem->type,PS_DATA_VECTOR);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 5*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_F64) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_F64);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 6*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->n != 3) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->n,3);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 7*(itemNum+1);
            }
            if(strcmp(mdItem->name,TAB_COL_3_NAME) != 0) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
                        itemNum,mdItem->name,TAB_COL_3_NAME);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 8*(itemNum+1);
            }
            break;
        case 3:
            if(mdItem->type != PS_DATA_VECTOR) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
                        itemNum,mdItem->type,PS_DATA_VECTOR);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 5*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_F32) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_F32);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 6*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->n != 3) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->n,3);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 7*(itemNum+1);
            }
            if(strcmp(mdItem->name,TAB_COL_2_NAME) != 0) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
                        itemNum,mdItem->name,TAB_COL_2_NAME);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 8*(itemNum+1);
            }
            break;
        case 4:
            if(mdItem->type != PS_DATA_VECTOR) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
                        itemNum,mdItem->type,PS_DATA_VECTOR);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 5*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->type.type != PS_TYPE_S32) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector type %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->type.type, PS_TYPE_S32);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 6*(itemNum+1);
            }
            if(((psVector*)mdItem->data.V)->n != 3) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
                        itemNum,((psVector*)mdItem->data.V)->n,3);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 7*(itemNum+1);
            }
            if(strcmp(mdItem->name,TAB_COL_1_NAME) != 0) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
                        itemNum,mdItem->name,TAB_COL_1_NAME);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 8*(itemNum+1);
            }
            break;
        case 5:
            if(mdItem->type != PS_DATA_ARRAY) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d type %d not as expected %d",
                        itemNum,mdItem->type,PS_DATA_ARRAY);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 5*(itemNum+1);
            }
            if(((psArray*)mdItem->data.V)->n != 3) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d vector size %d not as expected %d",
                        itemNum,((psArray*)mdItem->data.V)->n,3);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 7*(itemNum+1);
            }
            if(strcmp(mdItem->name,TAB_COL_0_NAME) != 0) {
                psError(PS_ERR_UNKNOWN,true,"Column #%d name %s not as expected %s",
                        itemNum,mdItem->name,TAB_COL_0_NAME);
                psDBDropTable(dbh,table);
                psDBCleanup(dbh);
                return 8*(itemNum+1);
            }
            break;

        default:
            break;
        }
        itemNum++;
    }
    psFree(mdIter);
    psFree(meta);

    // Attempt to dump columns from NULL database object
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL database");
    if(psDBDumpCols(NULL,table) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL when dumping columns from NULL database");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 10;
    }

    // Attempt to dump columns for NULL table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL table");
    if(psDBDumpCols(dbh,NULL) != NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect non-NULL when dumping columns from NULL table");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 11;
    }


    psDBDropTable(dbh, table);

    psFree(md);

    psDBCleanup(dbh);

    return 0;
}

// Testpoint #852, TPDBUpdateRows shall update rows in a test table ...
psS32 TPDBUpdateRows( void )
{
    psDB*            dbh       = NULL;
    const char*      table     = "table10";
    psArray*         ary       = NULL;
    psArray*         rowSet    = NULL;
    psMetadata*      row       = NULL;
    psMetadata*      where     = NULL;
    psMetadata*      updates   = NULL;
    psMetadata*      md        = NULL;
    int              chgRows   = 0;

    // Create database table definition
    md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL when initializing database");
        return 1;
    }

    // Create test table
    if(!psDBCreateTable(dbh, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false to create test table");
        psDBCleanup(dbh);
        return 2;
    }

    // Create array to hold rows to be added to test table
    rowSet = psArrayAlloc(3);
    rowSet->n = 0;

    row = _get_const_row1();
    psArrayAdd(rowSet, 0, row);
    psFree(row);

    row = _get_const_row2();
    psArrayAdd(rowSet, 0, row);
    psFree(row);

    row = _get_row();
    psArrayAdd(rowSet, 0, row);
    psFree(row);

    // Insert rows into test table
    if(!psDBInsertRows(dbh, table, rowSet)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for inserting rows");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 3;
    }

    // Create where metadata to specify update - only one row
    where = _get_where();

    // Create update metadata to specify values
    updates = _get_update_values(STR_2, S32_2, F32_2, F64_2, B_2);

    // Perform database update with valid parameters
    chgRows = psDBUpdateRows(dbh,table,where,updates);
    if(chgRows != 1) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return other than 1 for valid arguments");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 4;
    }
    // Verify row contents after update
    ary = psDBDumpRows(dbh, table);
    if (ary == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return from dump rows");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 5;
    }
    row = (psMetadata*)psArrayGet(ary, 0);
    if(!_check_row_update(row)) {
        psError(PS_ERR_UNKNOWN,true,"Update row not verified");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 6;
    }
    psFree(row);
    psFree(ary);

    // Attempt to update rows with NULL database
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL database");
    chgRows = psDBUpdateRows(NULL,table,where,updates);
    if(chgRows != -1) {
        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
                chgRows,-1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 7;
    }

    // Attempt to update rows with invalid table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid table");
    chgRows = psDBUpdateRows(dbh,"table999",where,updates);
    if(chgRows != -1) {
        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
                chgRows,-1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 8;
    }

    // Attempt to update rows with NULL updates
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for NULL updates");
    chgRows = psDBUpdateRows(dbh,table,where,NULL);
    if(chgRows != -1) {
        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
                chgRows,-1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 8;
    }

    // Attempt to update rows with invalid where specifying non-existent column
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error message for invalid where");
    psFree(where);
    where = _get_invalid_where();
    chgRows = psDBUpdateRows(dbh,table,where,updates);
    if(chgRows != -1) {
        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
                chgRows,-1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 9;
    }

    // Attempt to update rows with bad value in where statement
    psFree(where);
    where = _get_where_bad_value();
    chgRows = psDBUpdateRows(dbh,table,where,updates);
    if(chgRows != 0) {
        psError(PS_ERR_UNKNOWN,true,"Updated rows %ld not as expected %ld",
                chgRows,0);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 10;
    }
    // Verify row contents after update - no change
    ary = psDBDumpRows(dbh, table);
    if (ary == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect NULL return from dump rows");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 11;
    }
    row = (psMetadata*)psArrayGet(ary, 0);
    if(!_check_row_update(row)) {
        psError(PS_ERR_UNKNOWN,true,"Update row not verified");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 12;
    }
    psFree(row);
    psFree(ary);

    psFree(updates);
    psFree(where);
    psFree(rowSet);
    psDBDropTable(dbh, table);

    psFree(md);
    psDBCleanup(dbh);

    return 0;
}

// Testpoint #853, TPDBDeleteRows shall update rows in a test table ...
psS32 TPDBDeleteRows( void )
{
    psDB*         dbh       = NULL;
    const char*   table     = "table11";
    psArray*      ary       = NULL;
    psArray*      rowSet    = NULL;
    psMetadata*   where     = NULL;
    psMetadata*   row       = NULL;
    psMetadata*   md        = NULL;
    int           chgRows   = 0;

    // Create database table definition
    md = _get_CreateTableMetadata();

    // Initialize database connection
    dbh = _init_psDB();
    if (dbh == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for initialize database");
        return 1;
    }

    // Create test table
    if(!psDBCreateTable(dbh, table, md)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for creating test table");
        psDBCleanup(dbh);
        return 2;
    }

    // Create known data rows to put into test table
    rowSet = psArrayAlloc(3);
    rowSet->n = 0;
    row = _get_const_row1();
    psArrayAdd(rowSet, 0, row);
    psFree(row);
    row = _get_const_row2();
    psArrayAdd(rowSet, 0, row);
    psFree(row);
    row = _get_row();
    psArrayAdd(rowSet, 0, row);
    psFree(row);
    if(!psDBInsertRows(dbh, table, rowSet)) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return false for inserting data into table");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 3;
    }

    // Create where clause to specify the row to remove
    where = _get_where();

    // Delete row with valid arguments
    chgRows = psDBDeleteRows(dbh,table,where,10);
    if(chgRows != 1) {
        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
                chgRows,1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 4;
    }
    // Verify table contents
    ary = psDBDumpRows(dbh, table);
    if (ary == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for dump rows");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 5;
    }
    if (ary->n != 2) {
        psError(PS_ERR_UNKNOWN,true,"Remaining rows %d not as expected %d",
                ary->n,2);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 6;
    }
    psFree(ary);

    // Attempt to delete row just deleted again
    chgRows = psDBDeleteRows(dbh,table,where,10);
    if(chgRows != 0) {
        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
                chgRows,0);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 7;
    }
    // Verify table contents
    ary = psDBDumpRows(dbh, table);
    if (ary == NULL) {
        psError(PS_ERR_UNKNOWN,true,"Did not expect return NULL for dump rows");
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 8;
    }
    if (ary->n != 2) {
        psError(PS_ERR_UNKNOWN,true,"Remaining rows %d not as expected %d",
                ary->n,2);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 9;
    }
    psFree(ary);

    // Attempt to delete row with NULL database
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for NULL database");
    chgRows = psDBDeleteRows(NULL,table,where,10);
    if(chgRows > 0) {
        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
                chgRows, -1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 10;
    }

    // Attempt to delete row with invalid table
    psLogMsg(__func__,PS_LOG_INFO,"Following should generate error message for invalid table");
    chgRows = psDBDeleteRows(dbh,"table999",where,10);
    if(chgRows > 0) {
        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
                chgRows, -1);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 11;
    }

    // Attempt to delete row with NULL where - deletes all rows
    chgRows = psDBDeleteRows(dbh,table,NULL,10);
    if(chgRows != 2) {
        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
                chgRows, 2);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 12;
    }
    // Verify table contents
    ary = psDBDumpRows(dbh, table);
    if (ary != NULL && ary->n != 0) {
        psError(PS_ERR_UNKNOWN,true,"Remaining rows %d not as expected %d",
                ary->n,0);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 14;
    }
    psFree(ary);

    // Attempt to delete row with NULL where - deletes all rows from an empty table
    chgRows = psDBDeleteRows(dbh,table,NULL,10);
    if(chgRows != 0) {
        psError(PS_ERR_UNKNOWN,true,"Deleted rows %ld not as expected %ld",
                chgRows, 0);
        psDBDropTable(dbh,table);
        psDBCleanup(dbh);
        return 15;
    }

    psFree(where);
    psFree(rowSet);
    psDBDropTable(dbh, table);

    psFree(md);
    psDBCleanup(dbh);

    return 0;
}

//
// Tests for psDBCreate and psDBDrop can only be executed if the user
// has system admin privileges for the SQL server so the tests have been
// commented out.
//
// Testpoint #XXX, psDBCreate shall create a new test database.
//psS32 TPDBCreate( void )
//{
//    const char *test_db = "ps_test_db";
//    psS32 failed = 0;
//    psDB *dbh = NULL;
//
//    dbh = _init_psDB();
//    if (dbh == NULL) {
//        return 1;
//    }
//
//    psLogMsg( __func__, PS_LOG_INFO, "psDBCreate shall create new new test database.\n" );
//
//    failed = ! psDBCreate(dbh, test_db);
//    if (!failed) {
//        psDBDrop(dbh, test_db);
//    }
//
//    psDBCleanup(dbh);
//
//    return failed;
//}

// Testpoint #XXX, psDBDrop shall create a new test database.
//psS32 TPDBDrop( void )
//{
//    const char *test_db = "ps_test_db";
//    psS32 failed = 0;
//    psDB *dbh = NULL;
//
//    dbh = _init_psDB();
//    if (dbh == NULL) {
//        return 1;
//    }
//
//    psLogMsg( __func__, PS_LOG_INFO, "psDBDrop shall create/drop a new new test database.\n" );
//
//    failed = psDBCreate(dbh, test_db);
//    if (!failed) {
//        failed = ! psDBDrop(dbh, test_db);
//    }
//
//    psDBCleanup(dbh);
//
//    return failed;
//}

