/*
 * header.c
 *
 * Copyright (C) 2006  Joshua Hoblitt
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * program; see the file COPYING. If not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/*
 *
 * This file was generated by glueforge 1.04
 *
 * Do NOT directly edit this file.
 *
 */

#ifndef IPPDB_H
#define IPPDB_H 1

#include <pslib.h>

#ifdef __cplusplus
extern "C" {
#endif

/// @addtogroup ippdb
/// @{

/** Opens a new database connection
 *
 *  @return A new psDB object if the database connection is successful or NULL
 *  on failure.
 */

psDB *ippdbInit(
    const char      *host,              ///< Database server hostname
    const char      *user,              ///< Database username
    const char      *passwd,            ///< Database password
    const char      *dbname,            ///< Database table.namespace
    unsigned int    port                ///< Database port
);

/** Closes a database connection
 */

void ippdbCleanup(
    psDB            *dbh                ///< Database handle
);

/** Formats and prints a metadata
 *
 * Any internal use fields are stripped.
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool ippdbPrintMetadata(
    FILE            *stream,            ///< a stream
    psMetadata      *md,                ///< An array of metadata
    bool            mdcf                ///< format as mdconfig or simple
);

/** Formats and prints a metadata
 *
 * The metadata is printed verbatium without removing any fields.
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool ippdbPrintMetadataRaw(
    FILE            *stream,            ///< a stream
    psMetadata      *md,                ///< An array of metadata
    bool            mdcf                ///< format as mdconfig or simple
);

/** Formats and prints an array of metadata
 *
 * Any internal use fields are stripped.
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool ippdbPrintMetadatas(
    FILE            *stream,            ///< a stream
    psArray         *mds,               ///< An array of metadata
    const char      *mdname,            ///< name of the metadata(s)
    bool            mdcf                ///< format as mdconfig or simple
);

/** Formats and prints an array of metadata
 *
 * The metadatas are printed verbatium without removing any fields.
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool ippdbPrintMetadatasRaw(
    FILE            *stream,            ///< a stream
    psArray         *mds,               ///< An array of metadata
    const char      *mdname,            ///< name of the metadata(s)
    bool            mdcf                ///< format as mdconfig or simple
);

/** pzDataStoreRow data structure
 *
 * Structure for representing a single row of pzDataStore table data.
 */

typedef struct {
    char            *camera;
    char            *telescope;
    char            *uri;
    psTime*         epoch;
} pzDataStoreRow;

/** Creates a new pzDataStoreRow object
 *
 *  @return A new pzDataStoreRow object or NULL on failure.
 */

pzDataStoreRow *pzDataStoreRowAlloc(
    const char      *camera,
    const char      *telescope,
    const char      *uri,
    psTime*         epoch
);

/** Creates a new pzDataStore table
 *
 * @return true on success
 */

bool pzDataStoreCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a pzDataStore table
 *
 * @return true on success
 */

bool pzDataStoreDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzDataStoreInsert(
    psDB            *dbh,               ///< Database handle
    const char      *camera,
    const char      *telescope,
    const char      *uri,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pzDataStoreDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single pzDataStoreRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzDataStoreInsertObject(
    psDB            *dbh,               ///< Database handle
    pzDataStoreRow  *object             ///< pzDataStoreRow object
);

/** Insert an array of pzDataStoreRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool pzDataStoreInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of pzDataStoreRow objects
);

/** Insert data from a binary FITS table pzDataStoreRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool pzDataStoreInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool pzDataStoreSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a pzDataStoreRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pzDataStoreMetadataFromObject(
    const pzDataStoreRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A pzDataStoreRow pointer or NULL on error
 */

pzDataStoreRow *pzDataStoreObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as pzDataStoreRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *pzDataStoreSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an pzDataStore
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool pzDataStoreDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pzDataStoreRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pzDataStoreDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of pzDataStoreRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pzDataStorePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pzDataStoreRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pzDataStoreRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pzDataStorePrintObject(
    FILE            *stream,            ///< a stream
    pzDataStoreRow *object,    ///< an pzDataStoreRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** summitExpRow data structure
 *
 * Structure for representing a single row of summitExp table data.
 */

typedef struct {
    char            *exp_name;
    char            *camera;
    char            *telescope;
    psTime*         dateobs;
    char            *exp_type;
    char            *uri;
    psS32           imfiles;
    psS16           fault;
    psTime*         epoch;
} summitExpRow;

/** Creates a new summitExpRow object
 *
 *  @return A new summitExpRow object or NULL on failure.
 */

summitExpRow *summitExpRowAlloc(
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *exp_type,
    const char      *uri,
    psS32           imfiles,
    psS16           fault,
    psTime*         epoch
);

/** Creates a new summitExp table
 *
 * @return true on success
 */

bool summitExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a summitExp table
 *
 * @return true on success
 */

bool summitExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool summitExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *exp_type,
    const char      *uri,
    psS32           imfiles,
    psS16           fault,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long summitExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single summitExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool summitExpInsertObject(
    psDB            *dbh,               ///< Database handle
    summitExpRow    *object             ///< summitExpRow object
);

/** Insert an array of summitExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool summitExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of summitExpRow objects
);

/** Insert data from a binary FITS table summitExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool summitExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool summitExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a summitExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *summitExpMetadataFromObject(
    const summitExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A summitExpRow pointer or NULL on error
 */

summitExpRow *summitExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as summitExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *summitExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an summitExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool summitExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const summitExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long summitExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of summitExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool summitExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of summitExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an summitExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool summitExpPrintObject(
    FILE            *stream,            ///< a stream
    summitExpRow *object,    ///< an summitExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** summitImfileRow data structure
 *
 * Structure for representing a single row of summitImfile table data.
 */

typedef struct {
    char            *exp_name;
    char            *camera;
    char            *telescope;
    char            *file_id;
    psS32           bytes;
    char            *md5sum;
    char            *class;
    char            *class_id;
    char            *uri;
    psTime*         epoch;
} summitImfileRow;

/** Creates a new summitImfileRow object
 *
 *  @return A new summitImfileRow object or NULL on failure.
 */

summitImfileRow *summitImfileRowAlloc(
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    const char      *file_id,
    psS32           bytes,
    const char      *md5sum,
    const char      *class,
    const char      *class_id,
    const char      *uri,
    psTime*         epoch
);

/** Creates a new summitImfile table
 *
 * @return true on success
 */

bool summitImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a summitImfile table
 *
 * @return true on success
 */

bool summitImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool summitImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    const char      *file_id,
    psS32           bytes,
    const char      *md5sum,
    const char      *class,
    const char      *class_id,
    const char      *uri,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long summitImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single summitImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool summitImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    summitImfileRow *object             ///< summitImfileRow object
);

/** Insert an array of summitImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool summitImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of summitImfileRow objects
);

/** Insert data from a binary FITS table summitImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool summitImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool summitImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a summitImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *summitImfileMetadataFromObject(
    const summitImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A summitImfileRow pointer or NULL on error
 */

summitImfileRow *summitImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as summitImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *summitImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an summitImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool summitImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const summitImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long summitImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of summitImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool summitImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of summitImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an summitImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool summitImfilePrintObject(
    FILE            *stream,            ///< a stream
    summitImfileRow *object,    ///< an summitImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** pzDownloadExpRow data structure
 *
 * Structure for representing a single row of pzDownloadExp table data.
 */

typedef struct {
    char            *exp_name;
    char            *camera;
    char            *telescope;
    char            *state;
    psTime*         epoch;
} pzDownloadExpRow;

/** Creates a new pzDownloadExpRow object
 *
 *  @return A new pzDownloadExpRow object or NULL on failure.
 */

pzDownloadExpRow *pzDownloadExpRowAlloc(
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    const char      *state,
    psTime*         epoch
);

/** Creates a new pzDownloadExp table
 *
 * @return true on success
 */

bool pzDownloadExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a pzDownloadExp table
 *
 * @return true on success
 */

bool pzDownloadExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzDownloadExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    const char      *state,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pzDownloadExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single pzDownloadExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzDownloadExpInsertObject(
    psDB            *dbh,               ///< Database handle
    pzDownloadExpRow *object             ///< pzDownloadExpRow object
);

/** Insert an array of pzDownloadExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool pzDownloadExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of pzDownloadExpRow objects
);

/** Insert data from a binary FITS table pzDownloadExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool pzDownloadExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool pzDownloadExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a pzDownloadExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pzDownloadExpMetadataFromObject(
    const pzDownloadExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A pzDownloadExpRow pointer or NULL on error
 */

pzDownloadExpRow *pzDownloadExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as pzDownloadExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *pzDownloadExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an pzDownloadExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool pzDownloadExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pzDownloadExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pzDownloadExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of pzDownloadExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pzDownloadExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pzDownloadExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pzDownloadExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pzDownloadExpPrintObject(
    FILE            *stream,            ///< a stream
    pzDownloadExpRow *object,    ///< an pzDownloadExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** pzDownloadImfileRow data structure
 *
 * Structure for representing a single row of pzDownloadImfile table data.
 */

typedef struct {
    char            *exp_name;
    char            *camera;
    char            *telescope;
    char            *class;
    char            *class_id;
    char            *uri;
    psS16           fault;
    psTime*         epoch;
} pzDownloadImfileRow;

/** Creates a new pzDownloadImfileRow object
 *
 *  @return A new pzDownloadImfileRow object or NULL on failure.
 */

pzDownloadImfileRow *pzDownloadImfileRowAlloc(
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    const char      *class,
    const char      *class_id,
    const char      *uri,
    psS16           fault,
    psTime*         epoch
);

/** Creates a new pzDownloadImfile table
 *
 * @return true on success
 */

bool pzDownloadImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a pzDownloadImfile table
 *
 * @return true on success
 */

bool pzDownloadImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzDownloadImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    const char      *class,
    const char      *class_id,
    const char      *uri,
    psS16           fault,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pzDownloadImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single pzDownloadImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzDownloadImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    pzDownloadImfileRow *object             ///< pzDownloadImfileRow object
);

/** Insert an array of pzDownloadImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool pzDownloadImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of pzDownloadImfileRow objects
);

/** Insert data from a binary FITS table pzDownloadImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool pzDownloadImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool pzDownloadImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a pzDownloadImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pzDownloadImfileMetadataFromObject(
    const pzDownloadImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A pzDownloadImfileRow pointer or NULL on error
 */

pzDownloadImfileRow *pzDownloadImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as pzDownloadImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *pzDownloadImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an pzDownloadImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool pzDownloadImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pzDownloadImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pzDownloadImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of pzDownloadImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pzDownloadImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pzDownloadImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pzDownloadImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pzDownloadImfilePrintObject(
    FILE            *stream,            ///< a stream
    pzDownloadImfileRow *object,    ///< an pzDownloadImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** newExpRow data structure
 *
 * Structure for representing a single row of newExp table data.
 */

typedef struct {
    psS64           exp_id;
    char            *tmp_exp_name;
    char            *tmp_camera;
    char            *tmp_telescope;
    char            *state;
    char            *workdir;
    char            *workdir_state;
    char            *reduction;
    char            *dvodb;
    char            *tess_id;
    char            *end_stage;
    char            *label;
    psTime*         epoch;
} newExpRow;

/** Creates a new newExpRow object
 *
 *  @return A new newExpRow object or NULL on failure.
 */

newExpRow *newExpRowAlloc(
    psS64           exp_id,
    const char      *tmp_exp_name,
    const char      *tmp_camera,
    const char      *tmp_telescope,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *reduction,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage,
    const char      *label,
    psTime*         epoch
);

/** Creates a new newExp table
 *
 * @return true on success
 */

bool newExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a newExp table
 *
 * @return true on success
 */

bool newExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool newExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           exp_id,
    const char      *tmp_exp_name,
    const char      *tmp_camera,
    const char      *tmp_telescope,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *reduction,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage,
    const char      *label,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long newExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single newExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool newExpInsertObject(
    psDB            *dbh,               ///< Database handle
    newExpRow       *object             ///< newExpRow object
);

/** Insert an array of newExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool newExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of newExpRow objects
);

/** Insert data from a binary FITS table newExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool newExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool newExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a newExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *newExpMetadataFromObject(
    const newExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A newExpRow pointer or NULL on error
 */

newExpRow *newExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as newExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *newExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an newExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool newExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const newExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long newExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of newExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool newExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of newExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an newExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool newExpPrintObject(
    FILE            *stream,            ///< a stream
    newExpRow *object,    ///< an newExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** newImfileRow data structure
 *
 * Structure for representing a single row of newImfile table data.
 */

typedef struct {
    psS64           exp_id;
    char            *tmp_class_id;
    char            *uri;
    psTime*         epoch;
} newImfileRow;

/** Creates a new newImfileRow object
 *
 *  @return A new newImfileRow object or NULL on failure.
 */

newImfileRow *newImfileRowAlloc(
    psS64           exp_id,
    const char      *tmp_class_id,
    const char      *uri,
    psTime*         epoch
);

/** Creates a new newImfile table
 *
 * @return true on success
 */

bool newImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a newImfile table
 *
 * @return true on success
 */

bool newImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool newImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           exp_id,
    const char      *tmp_class_id,
    const char      *uri,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long newImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single newImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool newImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    newImfileRow    *object             ///< newImfileRow object
);

/** Insert an array of newImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool newImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of newImfileRow objects
);

/** Insert data from a binary FITS table newImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool newImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool newImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a newImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *newImfileMetadataFromObject(
    const newImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A newImfileRow pointer or NULL on error
 */

newImfileRow *newImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as newImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *newImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an newImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool newImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const newImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long newImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of newImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool newImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of newImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an newImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool newImfilePrintObject(
    FILE            *stream,            ///< a stream
    newImfileRow *object,    ///< an newImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** rawExpRow data structure
 *
 * Structure for representing a single row of rawExp table data.
 */

typedef struct {
    psS64           exp_id;
    char            *exp_name;
    char            *camera;
    char            *telescope;
    psTime*         dateobs;
    char            *exp_tag;
    char            *exp_type;
    char            *filelevel;
    char            *workdir;
    char            *reduction;
    char            *dvodb;
    char            *tess_id;
    char            *end_stage;
    char            *filter;
    char            *comment;
    psF32           airmass;
    psF64           ra;
    psF64           decl;
    psF32           exp_time;
    psF32           sat_pixel_frac;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           alt;
    psF64           az;
    psF32           ccd_temp;
    psF64           posang;
    psF32           m1_x;
    psF32           m1_y;
    psF32           m1_z;
    psF32           m1_tip;
    psF32           m1_tilt;
    psF32           m2_x;
    psF32           m2_y;
    psF32           m2_z;
    psF32           m2_tip;
    psF32           m2_tilt;
    psF32           env_temperature;
    psF32           env_humidity;
    psF32           env_wind_speed;
    psF32           env_wind_dir;
    psF32           teltemp_m1;
    psF32           teltemp_m1cell;
    psF32           teltemp_m2;
    psF32           teltemp_spider;
    psF32           teltemp_truss;
    psF32           teltemp_extra;
    psF32           pon_time;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    char            *object;
    psF32           solang;
    char            *hostname;
    psS16           fault;
    psTime*         epoch;
} rawExpRow;

/** Creates a new rawExpRow object
 *
 *  @return A new rawExpRow object or NULL on failure.
 */

rawExpRow *rawExpRowAlloc(
    psS64           exp_id,
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *exp_tag,
    const char      *exp_type,
    const char      *filelevel,
    const char      *workdir,
    const char      *reduction,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage,
    const char      *filter,
    const char      *comment,
    psF32           airmass,
    psF64           ra,
    psF64           decl,
    psF32           exp_time,
    psF32           sat_pixel_frac,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           alt,
    psF64           az,
    psF32           ccd_temp,
    psF64           posang,
    psF32           m1_x,
    psF32           m1_y,
    psF32           m1_z,
    psF32           m1_tip,
    psF32           m1_tilt,
    psF32           m2_x,
    psF32           m2_y,
    psF32           m2_z,
    psF32           m2_tip,
    psF32           m2_tilt,
    psF32           env_temperature,
    psF32           env_humidity,
    psF32           env_wind_speed,
    psF32           env_wind_dir,
    psF32           teltemp_m1,
    psF32           teltemp_m1cell,
    psF32           teltemp_m2,
    psF32           teltemp_spider,
    psF32           teltemp_truss,
    psF32           teltemp_extra,
    psF32           pon_time,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *object,
    psF32           solang,
    const char      *hostname,
    psS16           fault,
    psTime*         epoch
);

/** Creates a new rawExp table
 *
 * @return true on success
 */

bool rawExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a rawExp table
 *
 * @return true on success
 */

bool rawExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           exp_id,
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *exp_tag,
    const char      *exp_type,
    const char      *filelevel,
    const char      *workdir,
    const char      *reduction,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage,
    const char      *filter,
    const char      *comment,
    psF32           airmass,
    psF64           ra,
    psF64           decl,
    psF32           exp_time,
    psF32           sat_pixel_frac,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           alt,
    psF64           az,
    psF32           ccd_temp,
    psF64           posang,
    psF32           m1_x,
    psF32           m1_y,
    psF32           m1_z,
    psF32           m1_tip,
    psF32           m1_tilt,
    psF32           m2_x,
    psF32           m2_y,
    psF32           m2_z,
    psF32           m2_tip,
    psF32           m2_tilt,
    psF32           env_temperature,
    psF32           env_humidity,
    psF32           env_wind_speed,
    psF32           env_wind_dir,
    psF32           teltemp_m1,
    psF32           teltemp_m1cell,
    psF32           teltemp_m2,
    psF32           teltemp_spider,
    psF32           teltemp_truss,
    psF32           teltemp_extra,
    psF32           pon_time,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *object,
    psF32           solang,
    const char      *hostname,
    psS16           fault,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long rawExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single rawExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawExpInsertObject(
    psDB            *dbh,               ///< Database handle
    rawExpRow       *object             ///< rawExpRow object
);

/** Insert an array of rawExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool rawExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of rawExpRow objects
);

/** Insert data from a binary FITS table rawExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool rawExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool rawExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a rawExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *rawExpMetadataFromObject(
    const rawExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A rawExpRow pointer or NULL on error
 */

rawExpRow *rawExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as rawExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *rawExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an rawExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool rawExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const rawExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long rawExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of rawExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool rawExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of rawExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an rawExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool rawExpPrintObject(
    FILE            *stream,            ///< a stream
    rawExpRow *object,    ///< an rawExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** rawImfileRow data structure
 *
 * Structure for representing a single row of rawImfile table data.
 */

typedef struct {
    psS64           exp_id;
    char            *exp_name;
    char            *camera;
    char            *telescope;
    psTime*         dateobs;
    char            *tmp_class_id;
    char            *class_id;
    char            *uri;
    char            *exp_type;
    char            *filelevel;
    char            *filter;
    char            *comment;
    psF32           airmass;
    psF64           ra;
    psF64           decl;
    psF32           exp_time;
    psF32           sat_pixel_frac;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           alt;
    psF64           az;
    psF32           ccd_temp;
    psF64           posang;
    psF32           m1_x;
    psF32           m1_y;
    psF32           m1_z;
    psF32           m1_tip;
    psF32           m1_tilt;
    psF32           m2_x;
    psF32           m2_y;
    psF32           m2_z;
    psF32           m2_tip;
    psF32           m2_tilt;
    psF32           env_temperature;
    psF32           env_humidity;
    psF32           env_wind_speed;
    psF32           env_wind_dir;
    psF32           teltemp_m1;
    psF32           teltemp_m1cell;
    psF32           teltemp_m2;
    psF32           teltemp_spider;
    psF32           teltemp_truss;
    psF32           teltemp_extra;
    psF32           pon_time;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    char            *object;
    char            *hostname;
    psS16           fault;
    psTime*         epoch;
} rawImfileRow;

/** Creates a new rawImfileRow object
 *
 *  @return A new rawImfileRow object or NULL on failure.
 */

rawImfileRow *rawImfileRowAlloc(
    psS64           exp_id,
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *tmp_class_id,
    const char      *class_id,
    const char      *uri,
    const char      *exp_type,
    const char      *filelevel,
    const char      *filter,
    const char      *comment,
    psF32           airmass,
    psF64           ra,
    psF64           decl,
    psF32           exp_time,
    psF32           sat_pixel_frac,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           alt,
    psF64           az,
    psF32           ccd_temp,
    psF64           posang,
    psF32           m1_x,
    psF32           m1_y,
    psF32           m1_z,
    psF32           m1_tip,
    psF32           m1_tilt,
    psF32           m2_x,
    psF32           m2_y,
    psF32           m2_z,
    psF32           m2_tip,
    psF32           m2_tilt,
    psF32           env_temperature,
    psF32           env_humidity,
    psF32           env_wind_speed,
    psF32           env_wind_dir,
    psF32           teltemp_m1,
    psF32           teltemp_m1cell,
    psF32           teltemp_m2,
    psF32           teltemp_spider,
    psF32           teltemp_truss,
    psF32           teltemp_extra,
    psF32           pon_time,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *object,
    const char      *hostname,
    psS16           fault,
    psTime*         epoch
);

/** Creates a new rawImfile table
 *
 * @return true on success
 */

bool rawImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a rawImfile table
 *
 * @return true on success
 */

bool rawImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           exp_id,
    const char      *exp_name,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *tmp_class_id,
    const char      *class_id,
    const char      *uri,
    const char      *exp_type,
    const char      *filelevel,
    const char      *filter,
    const char      *comment,
    psF32           airmass,
    psF64           ra,
    psF64           decl,
    psF32           exp_time,
    psF32           sat_pixel_frac,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           alt,
    psF64           az,
    psF32           ccd_temp,
    psF64           posang,
    psF32           m1_x,
    psF32           m1_y,
    psF32           m1_z,
    psF32           m1_tip,
    psF32           m1_tilt,
    psF32           m2_x,
    psF32           m2_y,
    psF32           m2_z,
    psF32           m2_tip,
    psF32           m2_tilt,
    psF32           env_temperature,
    psF32           env_humidity,
    psF32           env_wind_speed,
    psF32           env_wind_dir,
    psF32           teltemp_m1,
    psF32           teltemp_m1cell,
    psF32           teltemp_m2,
    psF32           teltemp_spider,
    psF32           teltemp_truss,
    psF32           teltemp_extra,
    psF32           pon_time,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *object,
    const char      *hostname,
    psS16           fault,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long rawImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single rawImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    rawImfileRow    *object             ///< rawImfileRow object
);

/** Insert an array of rawImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool rawImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of rawImfileRow objects
);

/** Insert data from a binary FITS table rawImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool rawImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool rawImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a rawImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *rawImfileMetadataFromObject(
    const rawImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A rawImfileRow pointer or NULL on error
 */

rawImfileRow *rawImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as rawImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *rawImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an rawImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool rawImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const rawImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long rawImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of rawImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool rawImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of rawImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an rawImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool rawImfilePrintObject(
    FILE            *stream,            ///< a stream
    rawImfileRow *object,    ///< an rawImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** guidePendingExpRow data structure
 *
 * Structure for representing a single row of guidePendingExp table data.
 */

typedef struct {
    psS64           guide_id;
    psS64           exp_id;
    char            *recipe;
} guidePendingExpRow;

/** Creates a new guidePendingExpRow object
 *
 *  @return A new guidePendingExpRow object or NULL on failure.
 */

guidePendingExpRow *guidePendingExpRowAlloc(
    psS64           guide_id,
    psS64           exp_id,
    const char      *recipe
);

/** Creates a new guidePendingExp table
 *
 * @return true on success
 */

bool guidePendingExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a guidePendingExp table
 *
 * @return true on success
 */

bool guidePendingExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool guidePendingExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           guide_id,
    psS64           exp_id,
    const char      *recipe
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long guidePendingExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single guidePendingExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool guidePendingExpInsertObject(
    psDB            *dbh,               ///< Database handle
    guidePendingExpRow *object             ///< guidePendingExpRow object
);

/** Insert an array of guidePendingExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool guidePendingExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of guidePendingExpRow objects
);

/** Insert data from a binary FITS table guidePendingExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool guidePendingExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool guidePendingExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a guidePendingExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *guidePendingExpMetadataFromObject(
    const guidePendingExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A guidePendingExpRow pointer or NULL on error
 */

guidePendingExpRow *guidePendingExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as guidePendingExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *guidePendingExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an guidePendingExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool guidePendingExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const guidePendingExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long guidePendingExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of guidePendingExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool guidePendingExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of guidePendingExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an guidePendingExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool guidePendingExpPrintObject(
    FILE            *stream,            ///< a stream
    guidePendingExpRow *object,    ///< an guidePendingExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** chipRunRow data structure
 *
 * Structure for representing a single row of chipRun table data.
 */

typedef struct {
    psS64           chip_id;
    psS64           exp_id;
    char            *state;
    char            *workdir;
    char            *workdir_state;
    char            *label;
    char            *reduction;
    char            *expgroup;
    char            *dvodb;
    char            *tess_id;
    char            *end_stage;
} chipRunRow;

/** Creates a new chipRunRow object
 *
 *  @return A new chipRunRow object or NULL on failure.
 */

chipRunRow *chipRunRowAlloc(
    psS64           chip_id,
    psS64           exp_id,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *label,
    const char      *reduction,
    const char      *expgroup,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage
);

/** Creates a new chipRun table
 *
 * @return true on success
 */

bool chipRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a chipRun table
 *
 * @return true on success
 */

bool chipRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool chipRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           chip_id,
    psS64           exp_id,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *label,
    const char      *reduction,
    const char      *expgroup,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long chipRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single chipRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool chipRunInsertObject(
    psDB            *dbh,               ///< Database handle
    chipRunRow      *object             ///< chipRunRow object
);

/** Insert an array of chipRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool chipRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of chipRunRow objects
);

/** Insert data from a binary FITS table chipRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool chipRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool chipRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a chipRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *chipRunMetadataFromObject(
    const chipRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A chipRunRow pointer or NULL on error
 */

chipRunRow *chipRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as chipRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *chipRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an chipRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool chipRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const chipRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long chipRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of chipRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool chipRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of chipRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an chipRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool chipRunPrintObject(
    FILE            *stream,            ///< a stream
    chipRunRow *object,    ///< an chipRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** chipProcessedImfileRow data structure
 *
 * Structure for representing a single row of chipProcessedImfile table data.
 */

typedef struct {
    psS64           chip_id;
    psS64           exp_id;
    char            *class_id;
    char            *uri;
    psF32           bg;
    psF32           bg_stdev;
    psF32           bg_mean_stdev;
    psF32           bias;
    psF32           bias_stdev;
    psF32           fringe_0;
    psF32           fringe_1;
    psF32           fringe_2;
    psF32           sigma_ra;
    psF32           sigma_dec;
    psF32           ap_resid;
    psF32           ap_resid_stdev;
    psF32           zp_mean;
    psF32           zp_stdev;
    psF32           fwhm_major;
    psF32           fwhm_minor;
    psF32           dtime_detrend;
    psF32           dtime_photom;
    psF32           dtime_astrom;
    char            *hostname;
    psS32           n_stars;
    psS32           n_extended;
    psS32           n_cr;
    psS32           n_astrom;
    char            *path_base;
    psS16           fault;
} chipProcessedImfileRow;

/** Creates a new chipProcessedImfileRow object
 *
 *  @return A new chipProcessedImfileRow object or NULL on failure.
 */

chipProcessedImfileRow *chipProcessedImfileRowAlloc(
    psS64           chip_id,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    psF32           bg,
    psF32           bg_stdev,
    psF32           bg_mean_stdev,
    psF32           bias,
    psF32           bias_stdev,
    psF32           fringe_0,
    psF32           fringe_1,
    psF32           fringe_2,
    psF32           sigma_ra,
    psF32           sigma_dec,
    psF32           ap_resid,
    psF32           ap_resid_stdev,
    psF32           zp_mean,
    psF32           zp_stdev,
    psF32           fwhm_major,
    psF32           fwhm_minor,
    psF32           dtime_detrend,
    psF32           dtime_photom,
    psF32           dtime_astrom,
    const char      *hostname,
    psS32           n_stars,
    psS32           n_extended,
    psS32           n_cr,
    psS32           n_astrom,
    const char      *path_base,
    psS16           fault
);

/** Creates a new chipProcessedImfile table
 *
 * @return true on success
 */

bool chipProcessedImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a chipProcessedImfile table
 *
 * @return true on success
 */

bool chipProcessedImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool chipProcessedImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           chip_id,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    psF32           bg,
    psF32           bg_stdev,
    psF32           bg_mean_stdev,
    psF32           bias,
    psF32           bias_stdev,
    psF32           fringe_0,
    psF32           fringe_1,
    psF32           fringe_2,
    psF32           sigma_ra,
    psF32           sigma_dec,
    psF32           ap_resid,
    psF32           ap_resid_stdev,
    psF32           zp_mean,
    psF32           zp_stdev,
    psF32           fwhm_major,
    psF32           fwhm_minor,
    psF32           dtime_detrend,
    psF32           dtime_photom,
    psF32           dtime_astrom,
    const char      *hostname,
    psS32           n_stars,
    psS32           n_extended,
    psS32           n_cr,
    psS32           n_astrom,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long chipProcessedImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single chipProcessedImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool chipProcessedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    chipProcessedImfileRow *object             ///< chipProcessedImfileRow object
);

/** Insert an array of chipProcessedImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool chipProcessedImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of chipProcessedImfileRow objects
);

/** Insert data from a binary FITS table chipProcessedImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool chipProcessedImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool chipProcessedImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a chipProcessedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *chipProcessedImfileMetadataFromObject(
    const chipProcessedImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A chipProcessedImfileRow pointer or NULL on error
 */

chipProcessedImfileRow *chipProcessedImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as chipProcessedImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *chipProcessedImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an chipProcessedImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool chipProcessedImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const chipProcessedImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long chipProcessedImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of chipProcessedImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool chipProcessedImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of chipProcessedImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an chipProcessedImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool chipProcessedImfilePrintObject(
    FILE            *stream,            ///< a stream
    chipProcessedImfileRow *object,    ///< an chipProcessedImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** chipMaskRow data structure
 *
 * Structure for representing a single row of chipMask table data.
 */

typedef struct {
    char            *label;
} chipMaskRow;

/** Creates a new chipMaskRow object
 *
 *  @return A new chipMaskRow object or NULL on failure.
 */

chipMaskRow *chipMaskRowAlloc(
    const char      *label
);

/** Creates a new chipMask table
 *
 * @return true on success
 */

bool chipMaskCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a chipMask table
 *
 * @return true on success
 */

bool chipMaskDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool chipMaskInsert(
    psDB            *dbh,               ///< Database handle
    const char      *label
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long chipMaskDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single chipMaskRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool chipMaskInsertObject(
    psDB            *dbh,               ///< Database handle
    chipMaskRow     *object             ///< chipMaskRow object
);

/** Insert an array of chipMaskRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool chipMaskInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of chipMaskRow objects
);

/** Insert data from a binary FITS table chipMaskRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool chipMaskInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool chipMaskSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a chipMaskRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *chipMaskMetadataFromObject(
    const chipMaskRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A chipMaskRow pointer or NULL on error
 */

chipMaskRow *chipMaskObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as chipMaskRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *chipMaskSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an chipMask
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool chipMaskDeleteObject(
    psDB            *dbh,               ///< Database handle
    const chipMaskRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long chipMaskDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of chipMaskRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool chipMaskPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of chipMaskRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an chipMaskRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool chipMaskPrintObject(
    FILE            *stream,            ///< a stream
    chipMaskRow *object,    ///< an chipMaskRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** camRunRow data structure
 *
 * Structure for representing a single row of camRun table data.
 */

typedef struct {
    psS64           cam_id;
    psS64           chip_id;
    char            *state;
    char            *workdir;
    char            *workdir_state;
    char            *label;
    char            *reduction;
    char            *expgroup;
    char            *dvodb;
    char            *tess_id;
    char            *end_stage;
} camRunRow;

/** Creates a new camRunRow object
 *
 *  @return A new camRunRow object or NULL on failure.
 */

camRunRow *camRunRowAlloc(
    psS64           cam_id,
    psS64           chip_id,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *label,
    const char      *reduction,
    const char      *expgroup,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage
);

/** Creates a new camRun table
 *
 * @return true on success
 */

bool camRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a camRun table
 *
 * @return true on success
 */

bool camRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool camRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           cam_id,
    psS64           chip_id,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *label,
    const char      *reduction,
    const char      *expgroup,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long camRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single camRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool camRunInsertObject(
    psDB            *dbh,               ///< Database handle
    camRunRow       *object             ///< camRunRow object
);

/** Insert an array of camRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool camRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of camRunRow objects
);

/** Insert data from a binary FITS table camRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool camRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool camRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a camRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *camRunMetadataFromObject(
    const camRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A camRunRow pointer or NULL on error
 */

camRunRow *camRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as camRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *camRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an camRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool camRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const camRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long camRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of camRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool camRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of camRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an camRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool camRunPrintObject(
    FILE            *stream,            ///< a stream
    camRunRow *object,    ///< an camRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** camProcessedExpRow data structure
 *
 * Structure for representing a single row of camProcessedExp table data.
 */

typedef struct {
    psS64           cam_id;
    char            *uri;
    psF32           bg;
    psF32           bg_stdev;
    psF32           bg_mean_stdev;
    psF32           bias;
    psF32           bias_stdev;
    psF32           fringe_0;
    psF32           fringe_1;
    psF32           fringe_2;
    psF32           sigma_ra;
    psF32           sigma_dec;
    psF32           ap_resid;
    psF32           ap_resid_stdev;
    psF32           zp_mean;
    psF32           zp_stdev;
    psF32           fwhm_major;
    psF32           fwhm_minor;
    psF32           dtime_detrend;
    psF32           dtime_photom;
    psF32           dtime_astrom;
    char            *hostname;
    psS32           n_stars;
    psS32           n_extended;
    psS32           n_cr;
    psS32           n_astrom;
    char            *path_base;
    psS16           fault;
} camProcessedExpRow;

/** Creates a new camProcessedExpRow object
 *
 *  @return A new camProcessedExpRow object or NULL on failure.
 */

camProcessedExpRow *camProcessedExpRowAlloc(
    psS64           cam_id,
    const char      *uri,
    psF32           bg,
    psF32           bg_stdev,
    psF32           bg_mean_stdev,
    psF32           bias,
    psF32           bias_stdev,
    psF32           fringe_0,
    psF32           fringe_1,
    psF32           fringe_2,
    psF32           sigma_ra,
    psF32           sigma_dec,
    psF32           ap_resid,
    psF32           ap_resid_stdev,
    psF32           zp_mean,
    psF32           zp_stdev,
    psF32           fwhm_major,
    psF32           fwhm_minor,
    psF32           dtime_detrend,
    psF32           dtime_photom,
    psF32           dtime_astrom,
    const char      *hostname,
    psS32           n_stars,
    psS32           n_extended,
    psS32           n_cr,
    psS32           n_astrom,
    const char      *path_base,
    psS16           fault
);

/** Creates a new camProcessedExp table
 *
 * @return true on success
 */

bool camProcessedExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a camProcessedExp table
 *
 * @return true on success
 */

bool camProcessedExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool camProcessedExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           cam_id,
    const char      *uri,
    psF32           bg,
    psF32           bg_stdev,
    psF32           bg_mean_stdev,
    psF32           bias,
    psF32           bias_stdev,
    psF32           fringe_0,
    psF32           fringe_1,
    psF32           fringe_2,
    psF32           sigma_ra,
    psF32           sigma_dec,
    psF32           ap_resid,
    psF32           ap_resid_stdev,
    psF32           zp_mean,
    psF32           zp_stdev,
    psF32           fwhm_major,
    psF32           fwhm_minor,
    psF32           dtime_detrend,
    psF32           dtime_photom,
    psF32           dtime_astrom,
    const char      *hostname,
    psS32           n_stars,
    psS32           n_extended,
    psS32           n_cr,
    psS32           n_astrom,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long camProcessedExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single camProcessedExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool camProcessedExpInsertObject(
    psDB            *dbh,               ///< Database handle
    camProcessedExpRow *object             ///< camProcessedExpRow object
);

/** Insert an array of camProcessedExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool camProcessedExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of camProcessedExpRow objects
);

/** Insert data from a binary FITS table camProcessedExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool camProcessedExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool camProcessedExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a camProcessedExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *camProcessedExpMetadataFromObject(
    const camProcessedExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A camProcessedExpRow pointer or NULL on error
 */

camProcessedExpRow *camProcessedExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as camProcessedExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *camProcessedExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an camProcessedExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool camProcessedExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const camProcessedExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long camProcessedExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of camProcessedExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool camProcessedExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of camProcessedExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an camProcessedExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool camProcessedExpPrintObject(
    FILE            *stream,            ///< a stream
    camProcessedExpRow *object,    ///< an camProcessedExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** camMaskRow data structure
 *
 * Structure for representing a single row of camMask table data.
 */

typedef struct {
    char            *label;
} camMaskRow;

/** Creates a new camMaskRow object
 *
 *  @return A new camMaskRow object or NULL on failure.
 */

camMaskRow *camMaskRowAlloc(
    const char      *label
);

/** Creates a new camMask table
 *
 * @return true on success
 */

bool camMaskCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a camMask table
 *
 * @return true on success
 */

bool camMaskDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool camMaskInsert(
    psDB            *dbh,               ///< Database handle
    const char      *label
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long camMaskDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single camMaskRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool camMaskInsertObject(
    psDB            *dbh,               ///< Database handle
    camMaskRow      *object             ///< camMaskRow object
);

/** Insert an array of camMaskRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool camMaskInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of camMaskRow objects
);

/** Insert data from a binary FITS table camMaskRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool camMaskInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool camMaskSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a camMaskRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *camMaskMetadataFromObject(
    const camMaskRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A camMaskRow pointer or NULL on error
 */

camMaskRow *camMaskObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as camMaskRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *camMaskSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an camMask
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool camMaskDeleteObject(
    psDB            *dbh,               ///< Database handle
    const camMaskRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long camMaskDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of camMaskRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool camMaskPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of camMaskRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an camMaskRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool camMaskPrintObject(
    FILE            *stream,            ///< a stream
    camMaskRow *object,    ///< an camMaskRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** fakeRunRow data structure
 *
 * Structure for representing a single row of fakeRun table data.
 */

typedef struct {
    psS64           fake_id;
    psS64           cam_id;
    char            *state;
    char            *workdir;
    char            *label;
    char            *reduction;
    char            *expgroup;
    char            *dvodb;
    char            *tess_id;
    char            *end_stage;
    psTime*         epoch;
} fakeRunRow;

/** Creates a new fakeRunRow object
 *
 *  @return A new fakeRunRow object or NULL on failure.
 */

fakeRunRow *fakeRunRowAlloc(
    psS64           fake_id,
    psS64           cam_id,
    const char      *state,
    const char      *workdir,
    const char      *label,
    const char      *reduction,
    const char      *expgroup,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage,
    psTime*         epoch
);

/** Creates a new fakeRun table
 *
 * @return true on success
 */

bool fakeRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a fakeRun table
 *
 * @return true on success
 */

bool fakeRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool fakeRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           fake_id,
    psS64           cam_id,
    const char      *state,
    const char      *workdir,
    const char      *label,
    const char      *reduction,
    const char      *expgroup,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long fakeRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single fakeRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool fakeRunInsertObject(
    psDB            *dbh,               ///< Database handle
    fakeRunRow      *object             ///< fakeRunRow object
);

/** Insert an array of fakeRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool fakeRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of fakeRunRow objects
);

/** Insert data from a binary FITS table fakeRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool fakeRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool fakeRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a fakeRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *fakeRunMetadataFromObject(
    const fakeRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A fakeRunRow pointer or NULL on error
 */

fakeRunRow *fakeRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as fakeRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *fakeRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an fakeRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool fakeRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const fakeRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long fakeRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of fakeRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool fakeRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of fakeRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an fakeRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool fakeRunPrintObject(
    FILE            *stream,            ///< a stream
    fakeRunRow *object,    ///< an fakeRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** fakeProcessedImfileRow data structure
 *
 * Structure for representing a single row of fakeProcessedImfile table data.
 */

typedef struct {
    psS64           fake_id;
    psS64           exp_id;
    char            *class_id;
    char            *uri;
    psF32           dtime_fake;
    char            *hostname;
    char            *path_base;
    psS16           fault;
    psTime*         epoch;
} fakeProcessedImfileRow;

/** Creates a new fakeProcessedImfileRow object
 *
 *  @return A new fakeProcessedImfileRow object or NULL on failure.
 */

fakeProcessedImfileRow *fakeProcessedImfileRowAlloc(
    psS64           fake_id,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    psF32           dtime_fake,
    const char      *hostname,
    const char      *path_base,
    psS16           fault,
    psTime*         epoch
);

/** Creates a new fakeProcessedImfile table
 *
 * @return true on success
 */

bool fakeProcessedImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a fakeProcessedImfile table
 *
 * @return true on success
 */

bool fakeProcessedImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool fakeProcessedImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           fake_id,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    psF32           dtime_fake,
    const char      *hostname,
    const char      *path_base,
    psS16           fault,
    psTime*         epoch
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long fakeProcessedImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single fakeProcessedImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool fakeProcessedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    fakeProcessedImfileRow *object             ///< fakeProcessedImfileRow object
);

/** Insert an array of fakeProcessedImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool fakeProcessedImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of fakeProcessedImfileRow objects
);

/** Insert data from a binary FITS table fakeProcessedImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool fakeProcessedImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool fakeProcessedImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a fakeProcessedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *fakeProcessedImfileMetadataFromObject(
    const fakeProcessedImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A fakeProcessedImfileRow pointer or NULL on error
 */

fakeProcessedImfileRow *fakeProcessedImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as fakeProcessedImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *fakeProcessedImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an fakeProcessedImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool fakeProcessedImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const fakeProcessedImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long fakeProcessedImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of fakeProcessedImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool fakeProcessedImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of fakeProcessedImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an fakeProcessedImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool fakeProcessedImfilePrintObject(
    FILE            *stream,            ///< a stream
    fakeProcessedImfileRow *object,    ///< an fakeProcessedImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** fakeMaskRow data structure
 *
 * Structure for representing a single row of fakeMask table data.
 */

typedef struct {
    char            *label;
} fakeMaskRow;

/** Creates a new fakeMaskRow object
 *
 *  @return A new fakeMaskRow object or NULL on failure.
 */

fakeMaskRow *fakeMaskRowAlloc(
    const char      *label
);

/** Creates a new fakeMask table
 *
 * @return true on success
 */

bool fakeMaskCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a fakeMask table
 *
 * @return true on success
 */

bool fakeMaskDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool fakeMaskInsert(
    psDB            *dbh,               ///< Database handle
    const char      *label
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long fakeMaskDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single fakeMaskRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool fakeMaskInsertObject(
    psDB            *dbh,               ///< Database handle
    fakeMaskRow     *object             ///< fakeMaskRow object
);

/** Insert an array of fakeMaskRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool fakeMaskInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of fakeMaskRow objects
);

/** Insert data from a binary FITS table fakeMaskRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool fakeMaskInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool fakeMaskSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a fakeMaskRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *fakeMaskMetadataFromObject(
    const fakeMaskRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A fakeMaskRow pointer or NULL on error
 */

fakeMaskRow *fakeMaskObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as fakeMaskRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *fakeMaskSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an fakeMask
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool fakeMaskDeleteObject(
    psDB            *dbh,               ///< Database handle
    const fakeMaskRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long fakeMaskDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of fakeMaskRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool fakeMaskPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of fakeMaskRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an fakeMaskRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool fakeMaskPrintObject(
    FILE            *stream,            ///< a stream
    fakeMaskRow *object,    ///< an fakeMaskRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** warpRunRow data structure
 *
 * Structure for representing a single row of warpRun table data.
 */

typedef struct {
    psS64           warp_id;
    psS64           fake_id;
    char            *mode;
    char            *state;
    char            *workdir;
    char            *workdir_state;
    char            *label;
    char            *dvodb;
    char            *tess_id;
    char            *end_stage;
    psTime*         registered;
    bool            magiced;
} warpRunRow;

/** Creates a new warpRunRow object
 *
 *  @return A new warpRunRow object or NULL on failure.
 */

warpRunRow *warpRunRowAlloc(
    psS64           warp_id,
    psS64           fake_id,
    const char      *mode,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *label,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage,
    psTime*         registered,
    bool            magiced
);

/** Creates a new warpRun table
 *
 * @return true on success
 */

bool warpRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a warpRun table
 *
 * @return true on success
 */

bool warpRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool warpRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           warp_id,
    psS64           fake_id,
    const char      *mode,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *label,
    const char      *dvodb,
    const char      *tess_id,
    const char      *end_stage,
    psTime*         registered,
    bool            magiced
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long warpRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single warpRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool warpRunInsertObject(
    psDB            *dbh,               ///< Database handle
    warpRunRow      *object             ///< warpRunRow object
);

/** Insert an array of warpRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool warpRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of warpRunRow objects
);

/** Insert data from a binary FITS table warpRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool warpRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool warpRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a warpRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *warpRunMetadataFromObject(
    const warpRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A warpRunRow pointer or NULL on error
 */

warpRunRow *warpRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as warpRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *warpRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an warpRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool warpRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const warpRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long warpRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of warpRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool warpRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of warpRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an warpRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool warpRunPrintObject(
    FILE            *stream,            ///< a stream
    warpRunRow *object,    ///< an warpRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** warpSkyCellMapRow data structure
 *
 * Structure for representing a single row of warpSkyCellMap table data.
 */

typedef struct {
    psS64           warp_id;
    char            *skycell_id;
    char            *tess_id;
    char            *class_id;
    psS16           fault;
} warpSkyCellMapRow;

/** Creates a new warpSkyCellMapRow object
 *
 *  @return A new warpSkyCellMapRow object or NULL on failure.
 */

warpSkyCellMapRow *warpSkyCellMapRowAlloc(
    psS64           warp_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *class_id,
    psS16           fault
);

/** Creates a new warpSkyCellMap table
 *
 * @return true on success
 */

bool warpSkyCellMapCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a warpSkyCellMap table
 *
 * @return true on success
 */

bool warpSkyCellMapDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool warpSkyCellMapInsert(
    psDB            *dbh,               ///< Database handle
    psS64           warp_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *class_id,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long warpSkyCellMapDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single warpSkyCellMapRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool warpSkyCellMapInsertObject(
    psDB            *dbh,               ///< Database handle
    warpSkyCellMapRow *object             ///< warpSkyCellMapRow object
);

/** Insert an array of warpSkyCellMapRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool warpSkyCellMapInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of warpSkyCellMapRow objects
);

/** Insert data from a binary FITS table warpSkyCellMapRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool warpSkyCellMapInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool warpSkyCellMapSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a warpSkyCellMapRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *warpSkyCellMapMetadataFromObject(
    const warpSkyCellMapRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A warpSkyCellMapRow pointer or NULL on error
 */

warpSkyCellMapRow *warpSkyCellMapObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as warpSkyCellMapRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *warpSkyCellMapSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an warpSkyCellMap
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool warpSkyCellMapDeleteObject(
    psDB            *dbh,               ///< Database handle
    const warpSkyCellMapRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long warpSkyCellMapDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of warpSkyCellMapRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool warpSkyCellMapPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of warpSkyCellMapRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an warpSkyCellMapRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool warpSkyCellMapPrintObject(
    FILE            *stream,            ///< a stream
    warpSkyCellMapRow *object,    ///< an warpSkyCellMapRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** warpSkyfileRow data structure
 *
 * Structure for representing a single row of warpSkyfile table data.
 */

typedef struct {
    psS64           warp_id;
    char            *skycell_id;
    char            *tess_id;
    char            *uri;
    char            *path_base;
    psF64           bg;
    psF64           bg_stdev;
    psF32           dtime_warp;
    char            *hostname;
    psF32           good_frac;
    psS32           xmin;
    psS32           xmax;
    psS32           ymin;
    psS32           ymax;
    bool            ignored;
    psS16           fault;
} warpSkyfileRow;

/** Creates a new warpSkyfileRow object
 *
 *  @return A new warpSkyfileRow object or NULL on failure.
 */

warpSkyfileRow *warpSkyfileRowAlloc(
    psS64           warp_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *uri,
    const char      *path_base,
    psF64           bg,
    psF64           bg_stdev,
    psF32           dtime_warp,
    const char      *hostname,
    psF32           good_frac,
    psS32           xmin,
    psS32           xmax,
    psS32           ymin,
    psS32           ymax,
    bool            ignored,
    psS16           fault
);

/** Creates a new warpSkyfile table
 *
 * @return true on success
 */

bool warpSkyfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a warpSkyfile table
 *
 * @return true on success
 */

bool warpSkyfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool warpSkyfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           warp_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *uri,
    const char      *path_base,
    psF64           bg,
    psF64           bg_stdev,
    psF32           dtime_warp,
    const char      *hostname,
    psF32           good_frac,
    psS32           xmin,
    psS32           xmax,
    psS32           ymin,
    psS32           ymax,
    bool            ignored,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long warpSkyfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single warpSkyfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool warpSkyfileInsertObject(
    psDB            *dbh,               ///< Database handle
    warpSkyfileRow  *object             ///< warpSkyfileRow object
);

/** Insert an array of warpSkyfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool warpSkyfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of warpSkyfileRow objects
);

/** Insert data from a binary FITS table warpSkyfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool warpSkyfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool warpSkyfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a warpSkyfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *warpSkyfileMetadataFromObject(
    const warpSkyfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A warpSkyfileRow pointer or NULL on error
 */

warpSkyfileRow *warpSkyfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as warpSkyfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *warpSkyfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an warpSkyfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool warpSkyfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const warpSkyfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long warpSkyfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of warpSkyfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool warpSkyfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of warpSkyfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an warpSkyfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool warpSkyfilePrintObject(
    FILE            *stream,            ///< a stream
    warpSkyfileRow *object,    ///< an warpSkyfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** warpMaskRow data structure
 *
 * Structure for representing a single row of warpMask table data.
 */

typedef struct {
    char            *label;
} warpMaskRow;

/** Creates a new warpMaskRow object
 *
 *  @return A new warpMaskRow object or NULL on failure.
 */

warpMaskRow *warpMaskRowAlloc(
    const char      *label
);

/** Creates a new warpMask table
 *
 * @return true on success
 */

bool warpMaskCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a warpMask table
 *
 * @return true on success
 */

bool warpMaskDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool warpMaskInsert(
    psDB            *dbh,               ///< Database handle
    const char      *label
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long warpMaskDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single warpMaskRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool warpMaskInsertObject(
    psDB            *dbh,               ///< Database handle
    warpMaskRow     *object             ///< warpMaskRow object
);

/** Insert an array of warpMaskRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool warpMaskInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of warpMaskRow objects
);

/** Insert data from a binary FITS table warpMaskRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool warpMaskInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool warpMaskSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a warpMaskRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *warpMaskMetadataFromObject(
    const warpMaskRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A warpMaskRow pointer or NULL on error
 */

warpMaskRow *warpMaskObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as warpMaskRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *warpMaskSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an warpMask
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool warpMaskDeleteObject(
    psDB            *dbh,               ///< Database handle
    const warpMaskRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long warpMaskDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of warpMaskRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool warpMaskPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of warpMaskRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an warpMaskRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool warpMaskPrintObject(
    FILE            *stream,            ///< a stream
    warpMaskRow *object,    ///< an warpMaskRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** diffRunRow data structure
 *
 * Structure for representing a single row of diffRun table data.
 */

typedef struct {
    psS64           diff_id;
    char            *state;
    char            *workdir;
    char            *dvodb;
    psTime*         registered;
    char            *skycell_id;
    char            *tess_id;
} diffRunRow;

/** Creates a new diffRunRow object
 *
 *  @return A new diffRunRow object or NULL on failure.
 */

diffRunRow *diffRunRowAlloc(
    psS64           diff_id,
    const char      *state,
    const char      *workdir,
    const char      *dvodb,
    psTime*         registered,
    const char      *skycell_id,
    const char      *tess_id
);

/** Creates a new diffRun table
 *
 * @return true on success
 */

bool diffRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a diffRun table
 *
 * @return true on success
 */

bool diffRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool diffRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           diff_id,
    const char      *state,
    const char      *workdir,
    const char      *dvodb,
    psTime*         registered,
    const char      *skycell_id,
    const char      *tess_id
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long diffRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single diffRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool diffRunInsertObject(
    psDB            *dbh,               ///< Database handle
    diffRunRow      *object             ///< diffRunRow object
);

/** Insert an array of diffRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool diffRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of diffRunRow objects
);

/** Insert data from a binary FITS table diffRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool diffRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool diffRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a diffRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *diffRunMetadataFromObject(
    const diffRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A diffRunRow pointer or NULL on error
 */

diffRunRow *diffRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as diffRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *diffRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an diffRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool diffRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const diffRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long diffRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of diffRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool diffRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of diffRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an diffRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool diffRunPrintObject(
    FILE            *stream,            ///< a stream
    diffRunRow *object,    ///< an diffRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** diffInputSkyfileRow data structure
 *
 * Structure for representing a single row of diffInputSkyfile table data.
 */

typedef struct {
    psS64           diff_id;
    bool            template;
    psS64           stack_id;
    psS64           warp_id;
    char            *skycell_id;
    char            *tess_id;
    char            *kind;
} diffInputSkyfileRow;

/** Creates a new diffInputSkyfileRow object
 *
 *  @return A new diffInputSkyfileRow object or NULL on failure.
 */

diffInputSkyfileRow *diffInputSkyfileRowAlloc(
    psS64           diff_id,
    bool            template,
    psS64           stack_id,
    psS64           warp_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *kind
);

/** Creates a new diffInputSkyfile table
 *
 * @return true on success
 */

bool diffInputSkyfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a diffInputSkyfile table
 *
 * @return true on success
 */

bool diffInputSkyfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool diffInputSkyfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           diff_id,
    bool            template,
    psS64           stack_id,
    psS64           warp_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *kind
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long diffInputSkyfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single diffInputSkyfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool diffInputSkyfileInsertObject(
    psDB            *dbh,               ///< Database handle
    diffInputSkyfileRow *object             ///< diffInputSkyfileRow object
);

/** Insert an array of diffInputSkyfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool diffInputSkyfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of diffInputSkyfileRow objects
);

/** Insert data from a binary FITS table diffInputSkyfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool diffInputSkyfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool diffInputSkyfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a diffInputSkyfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *diffInputSkyfileMetadataFromObject(
    const diffInputSkyfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A diffInputSkyfileRow pointer or NULL on error
 */

diffInputSkyfileRow *diffInputSkyfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as diffInputSkyfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *diffInputSkyfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an diffInputSkyfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool diffInputSkyfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const diffInputSkyfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long diffInputSkyfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of diffInputSkyfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool diffInputSkyfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of diffInputSkyfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an diffInputSkyfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool diffInputSkyfilePrintObject(
    FILE            *stream,            ///< a stream
    diffInputSkyfileRow *object,    ///< an diffInputSkyfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** diffSkyfileRow data structure
 *
 * Structure for representing a single row of diffSkyfile table data.
 */

typedef struct {
    psS64           diff_id;
    char            *uri;
    char            *path_base;
    psF64           bg;
    psF64           bg_stdev;
    psS32           stamps_num;
    psF32           stamps_rms;
    psS32           sources;
    psF32           dtime_diff;
    char            *hostname;
    psF32           good_frac;
    psS16           fault;
} diffSkyfileRow;

/** Creates a new diffSkyfileRow object
 *
 *  @return A new diffSkyfileRow object or NULL on failure.
 */

diffSkyfileRow *diffSkyfileRowAlloc(
    psS64           diff_id,
    const char      *uri,
    const char      *path_base,
    psF64           bg,
    psF64           bg_stdev,
    psS32           stamps_num,
    psF32           stamps_rms,
    psS32           sources,
    psF32           dtime_diff,
    const char      *hostname,
    psF32           good_frac,
    psS16           fault
);

/** Creates a new diffSkyfile table
 *
 * @return true on success
 */

bool diffSkyfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a diffSkyfile table
 *
 * @return true on success
 */

bool diffSkyfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool diffSkyfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           diff_id,
    const char      *uri,
    const char      *path_base,
    psF64           bg,
    psF64           bg_stdev,
    psS32           stamps_num,
    psF32           stamps_rms,
    psS32           sources,
    psF32           dtime_diff,
    const char      *hostname,
    psF32           good_frac,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long diffSkyfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single diffSkyfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool diffSkyfileInsertObject(
    psDB            *dbh,               ///< Database handle
    diffSkyfileRow  *object             ///< diffSkyfileRow object
);

/** Insert an array of diffSkyfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool diffSkyfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of diffSkyfileRow objects
);

/** Insert data from a binary FITS table diffSkyfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool diffSkyfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool diffSkyfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a diffSkyfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *diffSkyfileMetadataFromObject(
    const diffSkyfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A diffSkyfileRow pointer or NULL on error
 */

diffSkyfileRow *diffSkyfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as diffSkyfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *diffSkyfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an diffSkyfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool diffSkyfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const diffSkyfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long diffSkyfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of diffSkyfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool diffSkyfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of diffSkyfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an diffSkyfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool diffSkyfilePrintObject(
    FILE            *stream,            ///< a stream
    diffSkyfileRow *object,    ///< an diffSkyfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** stackRunRow data structure
 *
 * Structure for representing a single row of stackRun table data.
 */

typedef struct {
    psS64           stack_id;
    char            *state;
    char            *workdir;
    char            *dvodb;
    psTime*         registered;
    char            *skycell_id;
    char            *tess_id;
    char            *filter;
} stackRunRow;

/** Creates a new stackRunRow object
 *
 *  @return A new stackRunRow object or NULL on failure.
 */

stackRunRow *stackRunRowAlloc(
    psS64           stack_id,
    const char      *state,
    const char      *workdir,
    const char      *dvodb,
    psTime*         registered,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *filter
);

/** Creates a new stackRun table
 *
 * @return true on success
 */

bool stackRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a stackRun table
 *
 * @return true on success
 */

bool stackRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool stackRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           stack_id,
    const char      *state,
    const char      *workdir,
    const char      *dvodb,
    psTime*         registered,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *filter
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long stackRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single stackRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool stackRunInsertObject(
    psDB            *dbh,               ///< Database handle
    stackRunRow     *object             ///< stackRunRow object
);

/** Insert an array of stackRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool stackRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of stackRunRow objects
);

/** Insert data from a binary FITS table stackRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool stackRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool stackRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a stackRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *stackRunMetadataFromObject(
    const stackRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A stackRunRow pointer or NULL on error
 */

stackRunRow *stackRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as stackRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *stackRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an stackRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool stackRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const stackRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long stackRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of stackRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool stackRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of stackRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an stackRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool stackRunPrintObject(
    FILE            *stream,            ///< a stream
    stackRunRow *object,    ///< an stackRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** stackInputSkyfileRow data structure
 *
 * Structure for representing a single row of stackInputSkyfile table data.
 */

typedef struct {
    psS64           stack_id;
    psS64           warp_id;
} stackInputSkyfileRow;

/** Creates a new stackInputSkyfileRow object
 *
 *  @return A new stackInputSkyfileRow object or NULL on failure.
 */

stackInputSkyfileRow *stackInputSkyfileRowAlloc(
    psS64           stack_id,
    psS64           warp_id
);

/** Creates a new stackInputSkyfile table
 *
 * @return true on success
 */

bool stackInputSkyfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a stackInputSkyfile table
 *
 * @return true on success
 */

bool stackInputSkyfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool stackInputSkyfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           stack_id,
    psS64           warp_id
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long stackInputSkyfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single stackInputSkyfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool stackInputSkyfileInsertObject(
    psDB            *dbh,               ///< Database handle
    stackInputSkyfileRow *object             ///< stackInputSkyfileRow object
);

/** Insert an array of stackInputSkyfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool stackInputSkyfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of stackInputSkyfileRow objects
);

/** Insert data from a binary FITS table stackInputSkyfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool stackInputSkyfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool stackInputSkyfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a stackInputSkyfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *stackInputSkyfileMetadataFromObject(
    const stackInputSkyfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A stackInputSkyfileRow pointer or NULL on error
 */

stackInputSkyfileRow *stackInputSkyfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as stackInputSkyfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *stackInputSkyfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an stackInputSkyfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool stackInputSkyfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const stackInputSkyfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long stackInputSkyfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of stackInputSkyfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool stackInputSkyfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of stackInputSkyfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an stackInputSkyfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool stackInputSkyfilePrintObject(
    FILE            *stream,            ///< a stream
    stackInputSkyfileRow *object,    ///< an stackInputSkyfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** stackSumSkyfileRow data structure
 *
 * Structure for representing a single row of stackSumSkyfile table data.
 */

typedef struct {
    psS64           stack_id;
    char            *uri;
    char            *path_base;
    psF64           bg;
    psF64           bg_stdev;
    psF32           dtime_stack;
    char            *hostname;
    psF32           good_frac;
    psS16           fault;
} stackSumSkyfileRow;

/** Creates a new stackSumSkyfileRow object
 *
 *  @return A new stackSumSkyfileRow object or NULL on failure.
 */

stackSumSkyfileRow *stackSumSkyfileRowAlloc(
    psS64           stack_id,
    const char      *uri,
    const char      *path_base,
    psF64           bg,
    psF64           bg_stdev,
    psF32           dtime_stack,
    const char      *hostname,
    psF32           good_frac,
    psS16           fault
);

/** Creates a new stackSumSkyfile table
 *
 * @return true on success
 */

bool stackSumSkyfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a stackSumSkyfile table
 *
 * @return true on success
 */

bool stackSumSkyfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool stackSumSkyfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           stack_id,
    const char      *uri,
    const char      *path_base,
    psF64           bg,
    psF64           bg_stdev,
    psF32           dtime_stack,
    const char      *hostname,
    psF32           good_frac,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long stackSumSkyfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single stackSumSkyfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool stackSumSkyfileInsertObject(
    psDB            *dbh,               ///< Database handle
    stackSumSkyfileRow *object             ///< stackSumSkyfileRow object
);

/** Insert an array of stackSumSkyfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool stackSumSkyfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of stackSumSkyfileRow objects
);

/** Insert data from a binary FITS table stackSumSkyfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool stackSumSkyfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool stackSumSkyfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a stackSumSkyfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *stackSumSkyfileMetadataFromObject(
    const stackSumSkyfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A stackSumSkyfileRow pointer or NULL on error
 */

stackSumSkyfileRow *stackSumSkyfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as stackSumSkyfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *stackSumSkyfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an stackSumSkyfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool stackSumSkyfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const stackSumSkyfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long stackSumSkyfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of stackSumSkyfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool stackSumSkyfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of stackSumSkyfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an stackSumSkyfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool stackSumSkyfilePrintObject(
    FILE            *stream,            ///< a stream
    stackSumSkyfileRow *object,    ///< an stackSumSkyfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detRunRow data structure
 *
 * Structure for representing a single row of detRun table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    char            *det_type;
    char            *mode;
    char            *state;
    char            *filelevel;
    char            *workdir;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    char            *reduction;
    char            *filter;
    psF32           airmass_min;
    psF32           airmass_max;
    psF32           exp_time_min;
    psF32           exp_time_max;
    psF32           ccd_temp_min;
    psF32           ccd_temp_max;
    psF64           posang_min;
    psF64           posang_max;
    psTime*         registered;
    psTime*         time_begin;
    psTime*         time_end;
    psTime*         use_begin;
    psTime*         use_end;
    psF32           solang_min;
    psF32           solang_max;
    char            *label;
    psS32           parent;
} detRunRow;

/** Creates a new detRunRow object
 *
 *  @return A new detRunRow object or NULL on failure.
 */

detRunRow *detRunRowAlloc(
    psS64           det_id,
    psS32           iteration,
    const char      *det_type,
    const char      *mode,
    const char      *state,
    const char      *filelevel,
    const char      *workdir,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    const char      *reduction,
    const char      *filter,
    psF32           airmass_min,
    psF32           airmass_max,
    psF32           exp_time_min,
    psF32           exp_time_max,
    psF32           ccd_temp_min,
    psF32           ccd_temp_max,
    psF64           posang_min,
    psF64           posang_max,
    psTime*         registered,
    psTime*         time_begin,
    psTime*         time_end,
    psTime*         use_begin,
    psTime*         use_end,
    psF32           solang_min,
    psF32           solang_max,
    const char      *label,
    psS32           parent
);

/** Creates a new detRun table
 *
 * @return true on success
 */

bool detRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detRun table
 *
 * @return true on success
 */

bool detRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    const char      *det_type,
    const char      *mode,
    const char      *state,
    const char      *filelevel,
    const char      *workdir,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    const char      *reduction,
    const char      *filter,
    psF32           airmass_min,
    psF32           airmass_max,
    psF32           exp_time_min,
    psF32           exp_time_max,
    psF32           ccd_temp_min,
    psF32           ccd_temp_max,
    psF64           posang_min,
    psF64           posang_max,
    psTime*         registered,
    psTime*         time_begin,
    psTime*         time_end,
    psTime*         use_begin,
    psTime*         use_end,
    psF32           solang_min,
    psF32           solang_max,
    const char      *label,
    psS32           parent
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detRunInsertObject(
    psDB            *dbh,               ///< Database handle
    detRunRow       *object             ///< detRunRow object
);

/** Insert an array of detRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detRunRow objects
);

/** Insert data from a binary FITS table detRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detRunMetadataFromObject(
    const detRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detRunRow pointer or NULL on error
 */

detRunRow *detRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detRunPrintObject(
    FILE            *stream,            ///< a stream
    detRunRow *object,    ///< an detRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detInputExpRow data structure
 *
 * Structure for representing a single row of detInputExp table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    psS64           exp_id;
    bool            include;
} detInputExpRow;

/** Creates a new detInputExpRow object
 *
 *  @return A new detInputExpRow object or NULL on failure.
 */

detInputExpRow *detInputExpRowAlloc(
    psS64           det_id,
    psS32           iteration,
    psS64           exp_id,
    bool            include
);

/** Creates a new detInputExp table
 *
 * @return true on success
 */

bool detInputExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detInputExp table
 *
 * @return true on success
 */

bool detInputExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detInputExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    psS64           exp_id,
    bool            include
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detInputExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detInputExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detInputExpInsertObject(
    psDB            *dbh,               ///< Database handle
    detInputExpRow  *object             ///< detInputExpRow object
);

/** Insert an array of detInputExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detInputExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detInputExpRow objects
);

/** Insert data from a binary FITS table detInputExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detInputExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detInputExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detInputExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detInputExpMetadataFromObject(
    const detInputExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detInputExpRow pointer or NULL on error
 */

detInputExpRow *detInputExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detInputExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detInputExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detInputExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detInputExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detInputExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detInputExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detInputExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detInputExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detInputExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detInputExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detInputExpPrintObject(
    FILE            *stream,            ///< a stream
    detInputExpRow *object,    ///< an detInputExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detProcessedImfileRow data structure
 *
 * Structure for representing a single row of detProcessedImfile table data.
 */

typedef struct {
    psS64           det_id;
    psS64           exp_id;
    char            *class_id;
    char            *uri;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           fringe_0;
    psF64           fringe_1;
    psF64           fringe_2;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    char            *path_base;
    psS16           fault;
} detProcessedImfileRow;

/** Creates a new detProcessedImfileRow object
 *
 *  @return A new detProcessedImfileRow object or NULL on failure.
 */

detProcessedImfileRow *detProcessedImfileRowAlloc(
    psS64           det_id,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           fringe_0,
    psF64           fringe_1,
    psF64           fringe_2,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Creates a new detProcessedImfile table
 *
 * @return true on success
 */

bool detProcessedImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detProcessedImfile table
 *
 * @return true on success
 */

bool detProcessedImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detProcessedImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           fringe_0,
    psF64           fringe_1,
    psF64           fringe_2,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detProcessedImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detProcessedImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detProcessedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detProcessedImfileRow *object             ///< detProcessedImfileRow object
);

/** Insert an array of detProcessedImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detProcessedImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detProcessedImfileRow objects
);

/** Insert data from a binary FITS table detProcessedImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detProcessedImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detProcessedImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detProcessedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detProcessedImfileMetadataFromObject(
    const detProcessedImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detProcessedImfileRow pointer or NULL on error
 */

detProcessedImfileRow *detProcessedImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detProcessedImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detProcessedImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detProcessedImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detProcessedImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detProcessedImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detProcessedImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detProcessedImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detProcessedImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detProcessedImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detProcessedImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detProcessedImfilePrintObject(
    FILE            *stream,            ///< a stream
    detProcessedImfileRow *object,    ///< an detProcessedImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detProcessedExpRow data structure
 *
 * Structure for representing a single row of detProcessedExp table data.
 */

typedef struct {
    psS64           det_id;
    psS64           exp_id;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           fringe_0;
    psF64           fringe_1;
    psF64           fringe_2;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    char            *path_base;
    psS16           fault;
} detProcessedExpRow;

/** Creates a new detProcessedExpRow object
 *
 *  @return A new detProcessedExpRow object or NULL on failure.
 */

detProcessedExpRow *detProcessedExpRowAlloc(
    psS64           det_id,
    psS64           exp_id,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           fringe_0,
    psF64           fringe_1,
    psF64           fringe_2,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Creates a new detProcessedExp table
 *
 * @return true on success
 */

bool detProcessedExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detProcessedExp table
 *
 * @return true on success
 */

bool detProcessedExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detProcessedExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS64           exp_id,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           fringe_0,
    psF64           fringe_1,
    psF64           fringe_2,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detProcessedExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detProcessedExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detProcessedExpInsertObject(
    psDB            *dbh,               ///< Database handle
    detProcessedExpRow *object             ///< detProcessedExpRow object
);

/** Insert an array of detProcessedExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detProcessedExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detProcessedExpRow objects
);

/** Insert data from a binary FITS table detProcessedExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detProcessedExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detProcessedExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detProcessedExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detProcessedExpMetadataFromObject(
    const detProcessedExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detProcessedExpRow pointer or NULL on error
 */

detProcessedExpRow *detProcessedExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detProcessedExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detProcessedExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detProcessedExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detProcessedExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detProcessedExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detProcessedExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detProcessedExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detProcessedExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detProcessedExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detProcessedExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detProcessedExpPrintObject(
    FILE            *stream,            ///< a stream
    detProcessedExpRow *object,    ///< an detProcessedExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detStackedImfileRow data structure
 *
 * Structure for representing a single row of detStackedImfile table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    char            *class_id;
    char            *uri;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    psS16           fault;
} detStackedImfileRow;

/** Creates a new detStackedImfileRow object
 *
 *  @return A new detStackedImfileRow object or NULL on failure.
 */

detStackedImfileRow *detStackedImfileRowAlloc(
    psS64           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    psS16           fault
);

/** Creates a new detStackedImfile table
 *
 * @return true on success
 */

bool detStackedImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detStackedImfile table
 *
 * @return true on success
 */

bool detStackedImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detStackedImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detStackedImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detStackedImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detStackedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detStackedImfileRow *object             ///< detStackedImfileRow object
);

/** Insert an array of detStackedImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detStackedImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detStackedImfileRow objects
);

/** Insert data from a binary FITS table detStackedImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detStackedImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detStackedImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detStackedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detStackedImfileMetadataFromObject(
    const detStackedImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detStackedImfileRow pointer or NULL on error
 */

detStackedImfileRow *detStackedImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detStackedImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detStackedImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detStackedImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detStackedImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detStackedImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detStackedImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detStackedImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detStackedImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detStackedImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detStackedImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detStackedImfilePrintObject(
    FILE            *stream,            ///< a stream
    detStackedImfileRow *object,    ///< an detStackedImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detNormalizedStatImfileRow data structure
 *
 * Structure for representing a single row of detNormalizedStatImfile table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    char            *class_id;
    psF32           norm;
    psS16           fault;
} detNormalizedStatImfileRow;

/** Creates a new detNormalizedStatImfileRow object
 *
 *  @return A new detNormalizedStatImfileRow object or NULL on failure.
 */

detNormalizedStatImfileRow *detNormalizedStatImfileRowAlloc(
    psS64           det_id,
    psS32           iteration,
    const char      *class_id,
    psF32           norm,
    psS16           fault
);

/** Creates a new detNormalizedStatImfile table
 *
 * @return true on success
 */

bool detNormalizedStatImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detNormalizedStatImfile table
 *
 * @return true on success
 */

bool detNormalizedStatImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedStatImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    const char      *class_id,
    psF32           norm,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detNormalizedStatImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detNormalizedStatImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedStatImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detNormalizedStatImfileRow *object             ///< detNormalizedStatImfileRow object
);

/** Insert an array of detNormalizedStatImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedStatImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detNormalizedStatImfileRow objects
);

/** Insert data from a binary FITS table detNormalizedStatImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detNormalizedStatImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detNormalizedStatImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detNormalizedStatImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detNormalizedStatImfileMetadataFromObject(
    const detNormalizedStatImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detNormalizedStatImfileRow pointer or NULL on error
 */

detNormalizedStatImfileRow *detNormalizedStatImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detNormalizedStatImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detNormalizedStatImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detNormalizedStatImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detNormalizedStatImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detNormalizedStatImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detNormalizedStatImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detNormalizedStatImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detNormalizedStatImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detNormalizedStatImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detNormalizedStatImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detNormalizedStatImfilePrintObject(
    FILE            *stream,            ///< a stream
    detNormalizedStatImfileRow *object,    ///< an detNormalizedStatImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detNormalizedImfileRow data structure
 *
 * Structure for representing a single row of detNormalizedImfile table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    char            *class_id;
    char            *uri;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    char            *path_base;
    psS16           fault;
} detNormalizedImfileRow;

/** Creates a new detNormalizedImfileRow object
 *
 *  @return A new detNormalizedImfileRow object or NULL on failure.
 */

detNormalizedImfileRow *detNormalizedImfileRowAlloc(
    psS64           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Creates a new detNormalizedImfile table
 *
 * @return true on success
 */

bool detNormalizedImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detNormalizedImfile table
 *
 * @return true on success
 */

bool detNormalizedImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detNormalizedImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detNormalizedImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detNormalizedImfileRow *object             ///< detNormalizedImfileRow object
);

/** Insert an array of detNormalizedImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detNormalizedImfileRow objects
);

/** Insert data from a binary FITS table detNormalizedImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detNormalizedImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detNormalizedImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detNormalizedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detNormalizedImfileMetadataFromObject(
    const detNormalizedImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detNormalizedImfileRow pointer or NULL on error
 */

detNormalizedImfileRow *detNormalizedImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detNormalizedImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detNormalizedImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detNormalizedImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detNormalizedImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detNormalizedImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detNormalizedImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detNormalizedImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detNormalizedImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detNormalizedImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detNormalizedImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detNormalizedImfilePrintObject(
    FILE            *stream,            ///< a stream
    detNormalizedImfileRow *object,    ///< an detNormalizedImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detNormalizedExpRow data structure
 *
 * Structure for representing a single row of detNormalizedExp table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    char            *path_base;
    psS16           fault;
} detNormalizedExpRow;

/** Creates a new detNormalizedExpRow object
 *
 *  @return A new detNormalizedExpRow object or NULL on failure.
 */

detNormalizedExpRow *detNormalizedExpRowAlloc(
    psS64           det_id,
    psS32           iteration,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Creates a new detNormalizedExp table
 *
 * @return true on success
 */

bool detNormalizedExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detNormalizedExp table
 *
 * @return true on success
 */

bool detNormalizedExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detNormalizedExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detNormalizedExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedExpInsertObject(
    psDB            *dbh,               ///< Database handle
    detNormalizedExpRow *object             ///< detNormalizedExpRow object
);

/** Insert an array of detNormalizedExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detNormalizedExpRow objects
);

/** Insert data from a binary FITS table detNormalizedExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detNormalizedExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detNormalizedExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detNormalizedExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detNormalizedExpMetadataFromObject(
    const detNormalizedExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detNormalizedExpRow pointer or NULL on error
 */

detNormalizedExpRow *detNormalizedExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detNormalizedExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detNormalizedExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detNormalizedExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detNormalizedExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detNormalizedExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detNormalizedExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detNormalizedExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detNormalizedExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detNormalizedExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detNormalizedExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detNormalizedExpPrintObject(
    FILE            *stream,            ///< a stream
    detNormalizedExpRow *object,    ///< an detNormalizedExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detResidImfileRow data structure
 *
 * Structure for representing a single row of detResidImfile table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    psS64           exp_id;
    char            *class_id;
    char            *uri;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           bg_skewness;
    psF64           bg_kurtosis;
    psF64           bin_stdev;
    psF64           fringe_0;
    psF64           fringe_1;
    psF64           fringe_2;
    psF64           fringe_resid_0;
    psF64           fringe_resid_1;
    psF64           fringe_resid_2;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    char            *path_base;
    psS16           fault;
} detResidImfileRow;

/** Creates a new detResidImfileRow object
 *
 *  @return A new detResidImfileRow object or NULL on failure.
 */

detResidImfileRow *detResidImfileRowAlloc(
    psS64           det_id,
    psS32           iteration,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           bg_skewness,
    psF64           bg_kurtosis,
    psF64           bin_stdev,
    psF64           fringe_0,
    psF64           fringe_1,
    psF64           fringe_2,
    psF64           fringe_resid_0,
    psF64           fringe_resid_1,
    psF64           fringe_resid_2,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Creates a new detResidImfile table
 *
 * @return true on success
 */

bool detResidImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detResidImfile table
 *
 * @return true on success
 */

bool detResidImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detResidImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           bg_skewness,
    psF64           bg_kurtosis,
    psF64           bin_stdev,
    psF64           fringe_0,
    psF64           fringe_1,
    psF64           fringe_2,
    psF64           fringe_resid_0,
    psF64           fringe_resid_1,
    psF64           fringe_resid_2,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detResidImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detResidImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detResidImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detResidImfileRow *object             ///< detResidImfileRow object
);

/** Insert an array of detResidImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detResidImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detResidImfileRow objects
);

/** Insert data from a binary FITS table detResidImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detResidImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detResidImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detResidImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detResidImfileMetadataFromObject(
    const detResidImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detResidImfileRow pointer or NULL on error
 */

detResidImfileRow *detResidImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detResidImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detResidImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detResidImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detResidImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detResidImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detResidImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detResidImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detResidImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detResidImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detResidImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detResidImfilePrintObject(
    FILE            *stream,            ///< a stream
    detResidImfileRow *object,    ///< an detResidImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detResidExpRow data structure
 *
 * Structure for representing a single row of detResidExp table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    psS64           exp_id;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           bg_skewness;
    psF64           bg_kurtosis;
    psF64           bin_stdev;
    psF64           fringe_0;
    psF64           fringe_1;
    psF64           fringe_2;
    psF64           fringe_resid_0;
    psF64           fringe_resid_1;
    psF64           fringe_resid_2;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    char            *path_base;
    bool            accept;
    psS16           fault;
} detResidExpRow;

/** Creates a new detResidExpRow object
 *
 *  @return A new detResidExpRow object or NULL on failure.
 */

detResidExpRow *detResidExpRowAlloc(
    psS64           det_id,
    psS32           iteration,
    psS64           exp_id,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           bg_skewness,
    psF64           bg_kurtosis,
    psF64           bin_stdev,
    psF64           fringe_0,
    psF64           fringe_1,
    psF64           fringe_2,
    psF64           fringe_resid_0,
    psF64           fringe_resid_1,
    psF64           fringe_resid_2,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    bool            accept,
    psS16           fault
);

/** Creates a new detResidExp table
 *
 * @return true on success
 */

bool detResidExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detResidExp table
 *
 * @return true on success
 */

bool detResidExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detResidExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    psS64           exp_id,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           bg_skewness,
    psF64           bg_kurtosis,
    psF64           bin_stdev,
    psF64           fringe_0,
    psF64           fringe_1,
    psF64           fringe_2,
    psF64           fringe_resid_0,
    psF64           fringe_resid_1,
    psF64           fringe_resid_2,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    bool            accept,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detResidExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detResidExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detResidExpInsertObject(
    psDB            *dbh,               ///< Database handle
    detResidExpRow  *object             ///< detResidExpRow object
);

/** Insert an array of detResidExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detResidExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detResidExpRow objects
);

/** Insert data from a binary FITS table detResidExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detResidExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detResidExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detResidExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detResidExpMetadataFromObject(
    const detResidExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detResidExpRow pointer or NULL on error
 */

detResidExpRow *detResidExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detResidExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detResidExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detResidExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detResidExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detResidExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detResidExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detResidExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detResidExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detResidExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detResidExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detResidExpPrintObject(
    FILE            *stream,            ///< a stream
    detResidExpRow *object,    ///< an detResidExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detRunSummaryRow data structure
 *
 * Structure for representing a single row of detRunSummary table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    bool            accept;
    psS16           fault;
} detRunSummaryRow;

/** Creates a new detRunSummaryRow object
 *
 *  @return A new detRunSummaryRow object or NULL on failure.
 */

detRunSummaryRow *detRunSummaryRowAlloc(
    psS64           det_id,
    psS32           iteration,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    bool            accept,
    psS16           fault
);

/** Creates a new detRunSummary table
 *
 * @return true on success
 */

bool detRunSummaryCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detRunSummary table
 *
 * @return true on success
 */

bool detRunSummaryDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detRunSummaryInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    bool            accept,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detRunSummaryDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detRunSummaryRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detRunSummaryInsertObject(
    psDB            *dbh,               ///< Database handle
    detRunSummaryRow *object             ///< detRunSummaryRow object
);

/** Insert an array of detRunSummaryRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detRunSummaryInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detRunSummaryRow objects
);

/** Insert data from a binary FITS table detRunSummaryRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detRunSummaryInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detRunSummarySelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detRunSummaryRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detRunSummaryMetadataFromObject(
    const detRunSummaryRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detRunSummaryRow pointer or NULL on error
 */

detRunSummaryRow *detRunSummaryObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detRunSummaryRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detRunSummarySelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detRunSummary
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detRunSummaryDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detRunSummaryRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detRunSummaryDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detRunSummaryRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detRunSummaryPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detRunSummaryRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detRunSummaryRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detRunSummaryPrintObject(
    FILE            *stream,            ///< a stream
    detRunSummaryRow *object,    ///< an detRunSummaryRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detRegisteredImfileRow data structure
 *
 * Structure for representing a single row of detRegisteredImfile table data.
 */

typedef struct {
    psS64           det_id;
    psS32           iteration;
    char            *class_id;
    char            *uri;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           user_1;
    psF64           user_2;
    psF64           user_3;
    psF64           user_4;
    psF64           user_5;
    char            *path_base;
    psS16           fault;
} detRegisteredImfileRow;

/** Creates a new detRegisteredImfileRow object
 *
 *  @return A new detRegisteredImfileRow object or NULL on failure.
 */

detRegisteredImfileRow *detRegisteredImfileRowAlloc(
    psS64           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Creates a new detRegisteredImfile table
 *
 * @return true on success
 */

bool detRegisteredImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detRegisteredImfile table
 *
 * @return true on success
 */

bool detRegisteredImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detRegisteredImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           user_1,
    psF64           user_2,
    psF64           user_3,
    psF64           user_4,
    psF64           user_5,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detRegisteredImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detRegisteredImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detRegisteredImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detRegisteredImfileRow *object             ///< detRegisteredImfileRow object
);

/** Insert an array of detRegisteredImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detRegisteredImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detRegisteredImfileRow objects
);

/** Insert data from a binary FITS table detRegisteredImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detRegisteredImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detRegisteredImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detRegisteredImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detRegisteredImfileMetadataFromObject(
    const detRegisteredImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detRegisteredImfileRow pointer or NULL on error
 */

detRegisteredImfileRow *detRegisteredImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detRegisteredImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detRegisteredImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detRegisteredImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detRegisteredImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detRegisteredImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detRegisteredImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detRegisteredImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detRegisteredImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detRegisteredImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detRegisteredImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detRegisteredImfilePrintObject(
    FILE            *stream,            ///< a stream
    detRegisteredImfileRow *object,    ///< an detRegisteredImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detCorrectedExpRow data structure
 *
 * Structure for representing a single row of detCorrectedExp table data.
 */

typedef struct {
    psS64           det_id;
    psS64           exp_id;
    char            *uri;
    psS64           corr_id;
    char            *corr_type;
    char            *recipe;
    char            *path_base;
    psS16           fault;
} detCorrectedExpRow;

/** Creates a new detCorrectedExpRow object
 *
 *  @return A new detCorrectedExpRow object or NULL on failure.
 */

detCorrectedExpRow *detCorrectedExpRowAlloc(
    psS64           det_id,
    psS64           exp_id,
    const char      *uri,
    psS64           corr_id,
    const char      *corr_type,
    const char      *recipe,
    const char      *path_base,
    psS16           fault
);

/** Creates a new detCorrectedExp table
 *
 * @return true on success
 */

bool detCorrectedExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detCorrectedExp table
 *
 * @return true on success
 */

bool detCorrectedExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detCorrectedExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS64           exp_id,
    const char      *uri,
    psS64           corr_id,
    const char      *corr_type,
    const char      *recipe,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detCorrectedExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detCorrectedExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detCorrectedExpInsertObject(
    psDB            *dbh,               ///< Database handle
    detCorrectedExpRow *object             ///< detCorrectedExpRow object
);

/** Insert an array of detCorrectedExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detCorrectedExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detCorrectedExpRow objects
);

/** Insert data from a binary FITS table detCorrectedExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detCorrectedExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detCorrectedExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detCorrectedExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detCorrectedExpMetadataFromObject(
    const detCorrectedExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detCorrectedExpRow pointer or NULL on error
 */

detCorrectedExpRow *detCorrectedExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detCorrectedExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detCorrectedExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detCorrectedExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detCorrectedExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detCorrectedExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detCorrectedExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detCorrectedExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detCorrectedExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detCorrectedExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detCorrectedExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detCorrectedExpPrintObject(
    FILE            *stream,            ///< a stream
    detCorrectedExpRow *object,    ///< an detCorrectedExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detCorrectedImfileRow data structure
 *
 * Structure for representing a single row of detCorrectedImfile table data.
 */

typedef struct {
    psS64           det_id;
    psS64           exp_id;
    char            *class_id;
    char            *uri;
    char            *path_base;
    psS16           fault;
} detCorrectedImfileRow;

/** Creates a new detCorrectedImfileRow object
 *
 *  @return A new detCorrectedImfileRow object or NULL on failure.
 */

detCorrectedImfileRow *detCorrectedImfileRowAlloc(
    psS64           det_id,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *path_base,
    psS16           fault
);

/** Creates a new detCorrectedImfile table
 *
 * @return true on success
 */

bool detCorrectedImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detCorrectedImfile table
 *
 * @return true on success
 */

bool detCorrectedImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detCorrectedImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           det_id,
    psS64           exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *path_base,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detCorrectedImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single detCorrectedImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detCorrectedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detCorrectedImfileRow *object             ///< detCorrectedImfileRow object
);

/** Insert an array of detCorrectedImfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool detCorrectedImfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of detCorrectedImfileRow objects
);

/** Insert data from a binary FITS table detCorrectedImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detCorrectedImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detCorrectedImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detCorrectedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detCorrectedImfileMetadataFromObject(
    const detCorrectedImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detCorrectedImfileRow pointer or NULL on error
 */

detCorrectedImfileRow *detCorrectedImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detCorrectedImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detCorrectedImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an detCorrectedImfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool detCorrectedImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const detCorrectedImfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detCorrectedImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of detCorrectedImfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detCorrectedImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of detCorrectedImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an detCorrectedImfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool detCorrectedImfilePrintObject(
    FILE            *stream,            ///< a stream
    detCorrectedImfileRow *object,    ///< an detCorrectedImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** magicRunRow data structure
 *
 * Structure for representing a single row of magicRun table data.
 */

typedef struct {
    psS64           magic_id;
    psS64           exp_id;
    char            *state;
    char            *workdir;
    char            *workdir_state;
    char            *label;
    char            *dvodb;
    psTime*         registered;
    psS16           fault;
} magicRunRow;

/** Creates a new magicRunRow object
 *
 *  @return A new magicRunRow object or NULL on failure.
 */

magicRunRow *magicRunRowAlloc(
    psS64           magic_id,
    psS64           exp_id,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *label,
    const char      *dvodb,
    psTime*         registered,
    psS16           fault
);

/** Creates a new magicRun table
 *
 * @return true on success
 */

bool magicRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a magicRun table
 *
 * @return true on success
 */

bool magicRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           magic_id,
    psS64           exp_id,
    const char      *state,
    const char      *workdir,
    const char      *workdir_state,
    const char      *label,
    const char      *dvodb,
    psTime*         registered,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single magicRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicRunInsertObject(
    psDB            *dbh,               ///< Database handle
    magicRunRow     *object             ///< magicRunRow object
);

/** Insert an array of magicRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool magicRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of magicRunRow objects
);

/** Insert data from a binary FITS table magicRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool magicRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool magicRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a magicRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *magicRunMetadataFromObject(
    const magicRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A magicRunRow pointer or NULL on error
 */

magicRunRow *magicRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as magicRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *magicRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an magicRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool magicRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const magicRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of magicRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of magicRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an magicRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicRunPrintObject(
    FILE            *stream,            ///< a stream
    magicRunRow *object,    ///< an magicRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** magicInputSkyfileRow data structure
 *
 * Structure for representing a single row of magicInputSkyfile table data.
 */

typedef struct {
    psS64           magic_id;
    psS64           diff_id;
    char            *node;
} magicInputSkyfileRow;

/** Creates a new magicInputSkyfileRow object
 *
 *  @return A new magicInputSkyfileRow object or NULL on failure.
 */

magicInputSkyfileRow *magicInputSkyfileRowAlloc(
    psS64           magic_id,
    psS64           diff_id,
    const char      *node
);

/** Creates a new magicInputSkyfile table
 *
 * @return true on success
 */

bool magicInputSkyfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a magicInputSkyfile table
 *
 * @return true on success
 */

bool magicInputSkyfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicInputSkyfileInsert(
    psDB            *dbh,               ///< Database handle
    psS64           magic_id,
    psS64           diff_id,
    const char      *node
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicInputSkyfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single magicInputSkyfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicInputSkyfileInsertObject(
    psDB            *dbh,               ///< Database handle
    magicInputSkyfileRow *object             ///< magicInputSkyfileRow object
);

/** Insert an array of magicInputSkyfileRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool magicInputSkyfileInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of magicInputSkyfileRow objects
);

/** Insert data from a binary FITS table magicInputSkyfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool magicInputSkyfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool magicInputSkyfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a magicInputSkyfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *magicInputSkyfileMetadataFromObject(
    const magicInputSkyfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A magicInputSkyfileRow pointer or NULL on error
 */

magicInputSkyfileRow *magicInputSkyfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as magicInputSkyfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *magicInputSkyfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an magicInputSkyfile
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool magicInputSkyfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const magicInputSkyfileRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicInputSkyfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of magicInputSkyfileRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicInputSkyfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of magicInputSkyfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an magicInputSkyfileRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicInputSkyfilePrintObject(
    FILE            *stream,            ///< a stream
    magicInputSkyfileRow *object,    ///< an magicInputSkyfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** magicTreeRow data structure
 *
 * Structure for representing a single row of magicTree table data.
 */

typedef struct {
    psS64           magic_id;
    char            *node;
    char            *dep;
} magicTreeRow;

/** Creates a new magicTreeRow object
 *
 *  @return A new magicTreeRow object or NULL on failure.
 */

magicTreeRow *magicTreeRowAlloc(
    psS64           magic_id,
    const char      *node,
    const char      *dep
);

/** Creates a new magicTree table
 *
 * @return true on success
 */

bool magicTreeCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a magicTree table
 *
 * @return true on success
 */

bool magicTreeDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicTreeInsert(
    psDB            *dbh,               ///< Database handle
    psS64           magic_id,
    const char      *node,
    const char      *dep
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicTreeDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single magicTreeRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicTreeInsertObject(
    psDB            *dbh,               ///< Database handle
    magicTreeRow    *object             ///< magicTreeRow object
);

/** Insert an array of magicTreeRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool magicTreeInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of magicTreeRow objects
);

/** Insert data from a binary FITS table magicTreeRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool magicTreeInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool magicTreeSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a magicTreeRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *magicTreeMetadataFromObject(
    const magicTreeRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A magicTreeRow pointer or NULL on error
 */

magicTreeRow *magicTreeObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as magicTreeRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *magicTreeSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an magicTree
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool magicTreeDeleteObject(
    psDB            *dbh,               ///< Database handle
    const magicTreeRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicTreeDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of magicTreeRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicTreePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of magicTreeRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an magicTreeRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicTreePrintObject(
    FILE            *stream,            ///< a stream
    magicTreeRow *object,    ///< an magicTreeRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** magicNodeResultRow data structure
 *
 * Structure for representing a single row of magicNodeResult table data.
 */

typedef struct {
    psS64           magic_id;
    char            *node;
    char            *uri;
    psS16           fault;
} magicNodeResultRow;

/** Creates a new magicNodeResultRow object
 *
 *  @return A new magicNodeResultRow object or NULL on failure.
 */

magicNodeResultRow *magicNodeResultRowAlloc(
    psS64           magic_id,
    const char      *node,
    const char      *uri,
    psS16           fault
);

/** Creates a new magicNodeResult table
 *
 * @return true on success
 */

bool magicNodeResultCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a magicNodeResult table
 *
 * @return true on success
 */

bool magicNodeResultDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicNodeResultInsert(
    psDB            *dbh,               ///< Database handle
    psS64           magic_id,
    const char      *node,
    const char      *uri,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicNodeResultDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single magicNodeResultRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicNodeResultInsertObject(
    psDB            *dbh,               ///< Database handle
    magicNodeResultRow *object             ///< magicNodeResultRow object
);

/** Insert an array of magicNodeResultRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool magicNodeResultInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of magicNodeResultRow objects
);

/** Insert data from a binary FITS table magicNodeResultRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool magicNodeResultInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool magicNodeResultSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a magicNodeResultRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *magicNodeResultMetadataFromObject(
    const magicNodeResultRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A magicNodeResultRow pointer or NULL on error
 */

magicNodeResultRow *magicNodeResultObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as magicNodeResultRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *magicNodeResultSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an magicNodeResult
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool magicNodeResultDeleteObject(
    psDB            *dbh,               ///< Database handle
    const magicNodeResultRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicNodeResultDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of magicNodeResultRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicNodeResultPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of magicNodeResultRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an magicNodeResultRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicNodeResultPrintObject(
    FILE            *stream,            ///< a stream
    magicNodeResultRow *object,    ///< an magicNodeResultRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** magicMaskRow data structure
 *
 * Structure for representing a single row of magicMask table data.
 */

typedef struct {
    psS64           magic_id;
    char            *uri;
    psS32           streaks;
    psS16           fault;
} magicMaskRow;

/** Creates a new magicMaskRow object
 *
 *  @return A new magicMaskRow object or NULL on failure.
 */

magicMaskRow *magicMaskRowAlloc(
    psS64           magic_id,
    const char      *uri,
    psS32           streaks,
    psS16           fault
);

/** Creates a new magicMask table
 *
 * @return true on success
 */

bool magicMaskCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a magicMask table
 *
 * @return true on success
 */

bool magicMaskDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicMaskInsert(
    psDB            *dbh,               ///< Database handle
    psS64           magic_id,
    const char      *uri,
    psS32           streaks,
    psS16           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicMaskDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single magicMaskRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool magicMaskInsertObject(
    psDB            *dbh,               ///< Database handle
    magicMaskRow    *object             ///< magicMaskRow object
);

/** Insert an array of magicMaskRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool magicMaskInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of magicMaskRow objects
);

/** Insert data from a binary FITS table magicMaskRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool magicMaskInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool magicMaskSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a magicMaskRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *magicMaskMetadataFromObject(
    const magicMaskRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A magicMaskRow pointer or NULL on error
 */

magicMaskRow *magicMaskObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as magicMaskRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *magicMaskSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an magicMask
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool magicMaskDeleteObject(
    psDB            *dbh,               ///< Database handle
    const magicMaskRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long magicMaskDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of magicMaskRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicMaskPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of magicMaskRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an magicMaskRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool magicMaskPrintObject(
    FILE            *stream,            ///< a stream
    magicMaskRow *object,    ///< an magicMaskRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** calDBRow data structure
 *
 * Structure for representing a single row of calDB table data.
 */

typedef struct {
    psS64           cal_id;
    char            *dvodb;
    char            *state;
} calDBRow;

/** Creates a new calDBRow object
 *
 *  @return A new calDBRow object or NULL on failure.
 */

calDBRow *calDBRowAlloc(
    psS64           cal_id,
    const char      *dvodb,
    const char      *state
);

/** Creates a new calDB table
 *
 * @return true on success
 */

bool calDBCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a calDB table
 *
 * @return true on success
 */

bool calDBDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool calDBInsert(
    psDB            *dbh,               ///< Database handle
    psS64           cal_id,
    const char      *dvodb,
    const char      *state
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long calDBDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single calDBRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool calDBInsertObject(
    psDB            *dbh,               ///< Database handle
    calDBRow        *object             ///< calDBRow object
);

/** Insert an array of calDBRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool calDBInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of calDBRow objects
);

/** Insert data from a binary FITS table calDBRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool calDBInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool calDBSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a calDBRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *calDBMetadataFromObject(
    const calDBRow  *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A calDBRow pointer or NULL on error
 */

calDBRow *calDBObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as calDBRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *calDBSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an calDB
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool calDBDeleteObject(
    psDB            *dbh,               ///< Database handle
    const calDBRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long calDBDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of calDBRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool calDBPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of calDBRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an calDBRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool calDBPrintObject(
    FILE            *stream,            ///< a stream
    calDBRow *object,    ///< an calDBRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** calRunRow data structure
 *
 * Structure for representing a single row of calRun table data.
 */

typedef struct {
    psS64           cal_id;
    char            *region;
    char            *last_step;
    char            *state;
} calRunRow;

/** Creates a new calRunRow object
 *
 *  @return A new calRunRow object or NULL on failure.
 */

calRunRow *calRunRowAlloc(
    psS64           cal_id,
    const char      *region,
    const char      *last_step,
    const char      *state
);

/** Creates a new calRun table
 *
 * @return true on success
 */

bool calRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a calRun table
 *
 * @return true on success
 */

bool calRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool calRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           cal_id,
    const char      *region,
    const char      *last_step,
    const char      *state
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long calRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single calRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool calRunInsertObject(
    psDB            *dbh,               ///< Database handle
    calRunRow       *object             ///< calRunRow object
);

/** Insert an array of calRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool calRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of calRunRow objects
);

/** Insert data from a binary FITS table calRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool calRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool calRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a calRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *calRunMetadataFromObject(
    const calRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A calRunRow pointer or NULL on error
 */

calRunRow *calRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as calRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *calRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an calRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool calRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const calRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long calRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of calRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool calRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of calRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an calRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool calRunPrintObject(
    FILE            *stream,            ///< a stream
    calRunRow *object,    ///< an calRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** flatcorrRunRow data structure
 *
 * Structure for representing a single row of flatcorrRun table data.
 */

typedef struct {
    psS64           corr_id;
    char            *dvodb;
    char            *filter;
    char            *state;
    char            *workdir;
    char            *label;
    char            *stats;
    char            *region;
} flatcorrRunRow;

/** Creates a new flatcorrRunRow object
 *
 *  @return A new flatcorrRunRow object or NULL on failure.
 */

flatcorrRunRow *flatcorrRunRowAlloc(
    psS64           corr_id,
    const char      *dvodb,
    const char      *filter,
    const char      *state,
    const char      *workdir,
    const char      *label,
    const char      *stats,
    const char      *region
);

/** Creates a new flatcorrRun table
 *
 * @return true on success
 */

bool flatcorrRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a flatcorrRun table
 *
 * @return true on success
 */

bool flatcorrRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool flatcorrRunInsert(
    psDB            *dbh,               ///< Database handle
    psS64           corr_id,
    const char      *dvodb,
    const char      *filter,
    const char      *state,
    const char      *workdir,
    const char      *label,
    const char      *stats,
    const char      *region
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long flatcorrRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single flatcorrRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool flatcorrRunInsertObject(
    psDB            *dbh,               ///< Database handle
    flatcorrRunRow  *object             ///< flatcorrRunRow object
);

/** Insert an array of flatcorrRunRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool flatcorrRunInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of flatcorrRunRow objects
);

/** Insert data from a binary FITS table flatcorrRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool flatcorrRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool flatcorrRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a flatcorrRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *flatcorrRunMetadataFromObject(
    const flatcorrRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A flatcorrRunRow pointer or NULL on error
 */

flatcorrRunRow *flatcorrRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as flatcorrRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *flatcorrRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an flatcorrRun
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool flatcorrRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const flatcorrRunRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long flatcorrRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of flatcorrRunRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool flatcorrRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of flatcorrRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an flatcorrRunRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool flatcorrRunPrintObject(
    FILE            *stream,            ///< a stream
    flatcorrRunRow *object,    ///< an flatcorrRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** flatcorrExpRow data structure
 *
 * Structure for representing a single row of flatcorrExp table data.
 */

typedef struct {
    psS64           corr_id;
    psS64           chip_id;
} flatcorrExpRow;

/** Creates a new flatcorrExpRow object
 *
 *  @return A new flatcorrExpRow object or NULL on failure.
 */

flatcorrExpRow *flatcorrExpRowAlloc(
    psS64           corr_id,
    psS64           chip_id
);

/** Creates a new flatcorrExp table
 *
 * @return true on success
 */

bool flatcorrExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a flatcorrExp table
 *
 * @return true on success
 */

bool flatcorrExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool flatcorrExpInsert(
    psDB            *dbh,               ///< Database handle
    psS64           corr_id,
    psS64           chip_id
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long flatcorrExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single flatcorrExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool flatcorrExpInsertObject(
    psDB            *dbh,               ///< Database handle
    flatcorrExpRow  *object             ///< flatcorrExpRow object
);

/** Insert an array of flatcorrExpRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool flatcorrExpInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of flatcorrExpRow objects
);

/** Insert data from a binary FITS table flatcorrExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool flatcorrExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool flatcorrExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a flatcorrExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *flatcorrExpMetadataFromObject(
    const flatcorrExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A flatcorrExpRow pointer or NULL on error
 */

flatcorrExpRow *flatcorrExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as flatcorrExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *flatcorrExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an flatcorrExp
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool flatcorrExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const flatcorrExpRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long flatcorrExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of flatcorrExpRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool flatcorrExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of flatcorrExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an flatcorrExpRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool flatcorrExpPrintObject(
    FILE            *stream,            ///< a stream
    flatcorrExpRow *object,    ///< an flatcorrExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** pstampDataStoreRow data structure
 *
 * Structure for representing a single row of pstampDataStore table data.
 */

typedef struct {
    psS64           ds_id;
    char            *state;
    char            *lastFileset;
    char            *outProduct;
    char            *uri;
} pstampDataStoreRow;

/** Creates a new pstampDataStoreRow object
 *
 *  @return A new pstampDataStoreRow object or NULL on failure.
 */

pstampDataStoreRow *pstampDataStoreRowAlloc(
    psS64           ds_id,
    const char      *state,
    const char      *lastFileset,
    const char      *outProduct,
    const char      *uri
);

/** Creates a new pstampDataStore table
 *
 * @return true on success
 */

bool pstampDataStoreCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a pstampDataStore table
 *
 * @return true on success
 */

bool pstampDataStoreDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pstampDataStoreInsert(
    psDB            *dbh,               ///< Database handle
    psS64           ds_id,
    const char      *state,
    const char      *lastFileset,
    const char      *outProduct,
    const char      *uri
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pstampDataStoreDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single pstampDataStoreRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pstampDataStoreInsertObject(
    psDB            *dbh,               ///< Database handle
    pstampDataStoreRow *object             ///< pstampDataStoreRow object
);

/** Insert an array of pstampDataStoreRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool pstampDataStoreInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of pstampDataStoreRow objects
);

/** Insert data from a binary FITS table pstampDataStoreRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool pstampDataStoreInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool pstampDataStoreSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a pstampDataStoreRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pstampDataStoreMetadataFromObject(
    const pstampDataStoreRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A pstampDataStoreRow pointer or NULL on error
 */

pstampDataStoreRow *pstampDataStoreObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as pstampDataStoreRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *pstampDataStoreSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an pstampDataStore
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool pstampDataStoreDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pstampDataStoreRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pstampDataStoreDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of pstampDataStoreRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pstampDataStorePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pstampDataStoreRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pstampDataStoreRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pstampDataStorePrintObject(
    FILE            *stream,            ///< a stream
    pstampDataStoreRow *object,    ///< an pstampDataStoreRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** pstampRequestRow data structure
 *
 * Structure for representing a single row of pstampRequest table data.
 */

typedef struct {
    psS64           req_id;
    psS64           ds_id;
    char            *state;
    char            *name;
    char            *reqType;
    char            *outProduct;
    char            *uri;
    psS32           fault;
} pstampRequestRow;

/** Creates a new pstampRequestRow object
 *
 *  @return A new pstampRequestRow object or NULL on failure.
 */

pstampRequestRow *pstampRequestRowAlloc(
    psS64           req_id,
    psS64           ds_id,
    const char      *state,
    const char      *name,
    const char      *reqType,
    const char      *outProduct,
    const char      *uri,
    psS32           fault
);

/** Creates a new pstampRequest table
 *
 * @return true on success
 */

bool pstampRequestCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a pstampRequest table
 *
 * @return true on success
 */

bool pstampRequestDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pstampRequestInsert(
    psDB            *dbh,               ///< Database handle
    psS64           req_id,
    psS64           ds_id,
    const char      *state,
    const char      *name,
    const char      *reqType,
    const char      *outProduct,
    const char      *uri,
    psS32           fault
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pstampRequestDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single pstampRequestRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pstampRequestInsertObject(
    psDB            *dbh,               ///< Database handle
    pstampRequestRow *object             ///< pstampRequestRow object
);

/** Insert an array of pstampRequestRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool pstampRequestInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of pstampRequestRow objects
);

/** Insert data from a binary FITS table pstampRequestRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool pstampRequestInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool pstampRequestSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a pstampRequestRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pstampRequestMetadataFromObject(
    const pstampRequestRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A pstampRequestRow pointer or NULL on error
 */

pstampRequestRow *pstampRequestObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as pstampRequestRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *pstampRequestSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an pstampRequest
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool pstampRequestDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pstampRequestRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pstampRequestDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of pstampRequestRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pstampRequestPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pstampRequestRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pstampRequestRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pstampRequestPrintObject(
    FILE            *stream,            ///< a stream
    pstampRequestRow *object,    ///< an pstampRequestRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** pstampJobRow data structure
 *
 * Structure for representing a single row of pstampJob table data.
 */

typedef struct {
    psS64           job_id;
    psS64           req_id;
    char            *rownum;
    char            *state;
    char            *jobType;
    psS32           fault;
    char            *uri;
    char            *outputBase;
    char            *args;
} pstampJobRow;

/** Creates a new pstampJobRow object
 *
 *  @return A new pstampJobRow object or NULL on failure.
 */

pstampJobRow *pstampJobRowAlloc(
    psS64           job_id,
    psS64           req_id,
    const char      *rownum,
    const char      *state,
    const char      *jobType,
    psS32           fault,
    const char      *uri,
    const char      *outputBase,
    const char      *args
);

/** Creates a new pstampJob table
 *
 * @return true on success
 */

bool pstampJobCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a pstampJob table
 *
 * @return true on success
 */

bool pstampJobDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pstampJobInsert(
    psDB            *dbh,               ///< Database handle
    psS64           job_id,
    psS64           req_id,
    const char      *rownum,
    const char      *state,
    const char      *jobType,
    psS32           fault,
    const char      *uri,
    const char      *outputBase,
    const char      *args
);

/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pstampJobDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/** Insert a single pstampJobRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pstampJobInsertObject(
    psDB            *dbh,               ///< Database handle
    pstampJobRow    *object             ///< pstampJobRow object
);

/** Insert an array of pstampJobRow object into a table
 *
 * This function constructs and inserts multiple rows based on it's parameters.
 *
 * @return true on success
 */

bool pstampJobInsertObjects(
    psDB            *dbh,               ///< Database handle
    psArray         *objects            ///< array of pstampJobRow objects
);

/** Insert data from a binary FITS table pstampJobRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool pstampJobInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool pstampJobSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a pstampJobRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pstampJobMetadataFromObject(
    const pstampJobRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A pstampJobRow pointer or NULL on error
 */

pstampJobRow *pstampJobObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as pstampJobRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *pstampJobSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes a row from the database coresponding to an pstampJob
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

bool pstampJobDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pstampJobRow *object    ///< Object to delete
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pstampJobDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** Formats and prints an array of pstampJobRow objects
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pstampJobPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pstampJobRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pstampJobRow object
 *
 * When mdcf is set the formated output is in psMetadataConfig
 * format, otherwise it is in a simple tabular format.
 *
 * @return true on success
 */

bool pstampJobPrintObject(
    FILE            *stream,            ///< a stream
    pstampJobRow *object,    ///< an pstampJobRow object
    bool            mdcf                ///< format as mdconfig or simple
);

/// @}

#ifdef __cplusplus
}
#endif

#endif // PSTAMPJOB_DB_H
