/*
 * 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 0.36
 *
 * 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
);

/** expTagCounterRow data structure
 *
 * Structure for representing a single row of expTagCounter table data.
 */

typedef struct {
    psU64           counter;
} expTagCounterRow;

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

expTagCounterRow *expTagCounterRowAlloc(
    psU64           counter
);

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

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

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

bool expTagCounterDropTable(
    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 expTagCounterInsert(
    psDB            *dbh,               ///< Database handle
    psU64           counter
);

/** 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 expTagCounterDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool expTagCounterInsertObject(
    psDB            *dbh,               ///< Database handle
    expTagCounterRow *object             ///< expTagCounterRow object
);

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

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

/** Insert data from a binary FITS table expTagCounterRow 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 expTagCounterInsertFits(
    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 expTagCounterSelectRowsFits(
    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 expTagCounterRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *expTagCounterMetadataFromObject(
    const expTagCounterRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *expTagCounterSelectRowObjects(
    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 expTagCounter
 *
 *  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 expTagCounterDeleteObject(
    psDB            *dbh,               ///< Database handle
    const expTagCounterRow *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 expTagCounterDeleteRowObjects(
    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 expTagCounterRow 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 expTagCounterPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of expTagCounterRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an expTagCounterRow 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 expTagCounterPrintObject(
    FILE            *stream,            ///< a stream
    expTagCounterRow *object,    ///< an expTagCounterRow 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_id;
    char            *camera;
    char            *telescope;
    psTime*         dateobs;
    char            *exp_type;
    char            *uri;
    psS32           imfiles;
} summitExpRow;

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

summitExpRow *summitExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *exp_type,
    const char      *uri,
    psS32           imfiles
);

/** 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_id,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *exp_type,
    const char      *uri,
    psS32           imfiles
);

/** 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_id;
    char            *camera;
    char            *telescope;
    char            *file_id;
    psS32           bytes;
    char            *md5sum;
    char            *class;
    char            *class_id;
    char            *uri;
} summitImfileRow;

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

summitImfileRow *summitImfileRowAlloc(
    const char      *exp_id,
    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
);

/** 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_id,
    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
);

/** 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
);
/** pzPendingExpRow data structure
 *
 * Structure for representing a single row of pzPendingExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
} pzPendingExpRow;

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

pzPendingExpRow *pzPendingExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope
);

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

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

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

bool pzPendingExpDropTable(
    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 pzPendingExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope
);

/** 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 pzPendingExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool pzPendingExpInsertObject(
    psDB            *dbh,               ///< Database handle
    pzPendingExpRow *object             ///< pzPendingExpRow object
);

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

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

/** Insert data from a binary FITS table pzPendingExpRow 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 pzPendingExpInsertFits(
    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 pzPendingExpSelectRowsFits(
    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 pzPendingExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pzPendingExpMetadataFromObject(
    const pzPendingExpRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *pzPendingExpSelectRowObjects(
    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 pzPendingExp
 *
 *  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 pzPendingExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pzPendingExpRow *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 pzPendingExpDeleteRowObjects(
    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 pzPendingExpRow 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 pzPendingExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pzPendingExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pzPendingExpRow 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 pzPendingExpPrintObject(
    FILE            *stream,            ///< a stream
    pzPendingExpRow *object,    ///< an pzPendingExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** pzPendingImfileRow data structure
 *
 * Structure for representing a single row of pzPendingImfile table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *class;
    char            *class_id;
    char            *exp_tag;
} pzPendingImfileRow;

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

pzPendingImfileRow *pzPendingImfileRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *class,
    const char      *class_id,
    const char      *exp_tag
);

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

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

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

bool pzPendingImfileDropTable(
    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 pzPendingImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *class,
    const char      *class_id,
    const char      *exp_tag
);

/** 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 pzPendingImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool pzPendingImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    pzPendingImfileRow *object             ///< pzPendingImfileRow object
);

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

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

/** Insert data from a binary FITS table pzPendingImfileRow 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 pzPendingImfileInsertFits(
    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 pzPendingImfileSelectRowsFits(
    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 pzPendingImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pzPendingImfileMetadataFromObject(
    const pzPendingImfileRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *pzPendingImfileSelectRowObjects(
    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 pzPendingImfile
 *
 *  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 pzPendingImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pzPendingImfileRow *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 pzPendingImfileDeleteRowObjects(
    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 pzPendingImfileRow 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 pzPendingImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pzPendingImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pzPendingImfileRow 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 pzPendingImfilePrintObject(
    FILE            *stream,            ///< a stream
    pzPendingImfileRow *object,    ///< an pzPendingImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** pzDoneExpRow data structure
 *
 * Structure for representing a single row of pzDoneExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
} pzDoneExpRow;

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

pzDoneExpRow *pzDoneExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope
);

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

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

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

bool pzDoneExpDropTable(
    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 pzDoneExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope
);

/** 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 pzDoneExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool pzDoneExpInsertObject(
    psDB            *dbh,               ///< Database handle
    pzDoneExpRow    *object             ///< pzDoneExpRow object
);

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

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

/** Insert data from a binary FITS table pzDoneExpRow 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 pzDoneExpInsertFits(
    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 pzDoneExpSelectRowsFits(
    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 pzDoneExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pzDoneExpMetadataFromObject(
    const pzDoneExpRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *pzDoneExpSelectRowObjects(
    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 pzDoneExp
 *
 *  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 pzDoneExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pzDoneExpRow *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 pzDoneExpDeleteRowObjects(
    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 pzDoneExpRow 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 pzDoneExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pzDoneExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pzDoneExpRow 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 pzDoneExpPrintObject(
    FILE            *stream,            ///< a stream
    pzDoneExpRow *object,    ///< an pzDoneExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** pzDoneImfileRow data structure
 *
 * Structure for representing a single row of pzDoneImfile table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *class;
    char            *class_id;
    char            *exp_tag;
    char            *uri;
} pzDoneImfileRow;

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

pzDoneImfileRow *pzDoneImfileRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *class,
    const char      *class_id,
    const char      *exp_tag,
    const char      *uri
);

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

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

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

bool pzDoneImfileDropTable(
    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 pzDoneImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *class,
    const char      *class_id,
    const char      *exp_tag,
    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 pzDoneImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool pzDoneImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    pzDoneImfileRow *object             ///< pzDoneImfileRow object
);

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

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

/** Insert data from a binary FITS table pzDoneImfileRow 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 pzDoneImfileInsertFits(
    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 pzDoneImfileSelectRowsFits(
    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 pzDoneImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pzDoneImfileMetadataFromObject(
    const pzDoneImfileRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *pzDoneImfileSelectRowObjects(
    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 pzDoneImfile
 *
 *  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 pzDoneImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const pzDoneImfileRow *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 pzDoneImfileDeleteRowObjects(
    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 pzDoneImfileRow 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 pzDoneImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of pzDoneImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an pzDoneImfileRow 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 pzDoneImfilePrintObject(
    FILE            *stream,            ///< a stream
    pzDoneImfileRow *object,    ///< an pzDoneImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** newExpRow data structure
 *
 * Structure for representing a single row of newExp table data.
 */

typedef struct {
    char            *exp_tag;
    char            *exp_id;
    char            *camera;
    char            *telescope;
    psS32           imfiles;
    char            *workdir;
} newExpRow;

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

newExpRow *newExpRowAlloc(
    const char      *exp_tag,
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    psS32           imfiles,
    const char      *workdir
);

/** 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
    const char      *exp_tag,
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    psS32           imfiles,
    const char      *workdir
);

/** 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 {
    char            *exp_tag;
    char            *class;
    char            *class_id;
    char            *uri;
} newImfileRow;

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

newImfileRow *newImfileRowAlloc(
    const char      *exp_tag,
    const char      *class,
    const char      *class_id,
    const char      *uri
);

/** 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
    const char      *exp_tag,
    const char      *class,
    const char      *class_id,
    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 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 {
    char            *exp_tag;
    char            *exp_id;
    char            *camera;
    char            *telescope;
    psTime*         dateobs;
    char            *exp_type;
    psS32           imfiles;
    char            *workdir;
    char            *filter;
    psF32           airmass;
    psF64           ra;
    psF64           decl;
    psF32           exp_time;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           alt;
    psF64           az;
    psF32           ccd_temp;
    psF64           posang;
    char            *object;
    psS16           fault;
} rawExpRow;

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

rawExpRow *rawExpRowAlloc(
    const char      *exp_tag,
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *exp_type,
    psS32           imfiles,
    const char      *workdir,
    const char      *filter,
    psF32           airmass,
    psF64           ra,
    psF64           decl,
    psF32           exp_time,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           alt,
    psF64           az,
    psF32           ccd_temp,
    psF64           posang,
    const char      *object,
    psS16           fault
);

/** 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
    const char      *exp_tag,
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    psTime*         dateobs,
    const char      *exp_type,
    psS32           imfiles,
    const char      *workdir,
    const char      *filter,
    psF32           airmass,
    psF64           ra,
    psF64           decl,
    psF32           exp_time,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           alt,
    psF64           az,
    psF32           ccd_temp,
    psF64           posang,
    const char      *object,
    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 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 {
    char            *exp_tag;
    char            *class;
    char            *class_id;
    char            *uri;
    char            *exp_type;
    char            *filter;
    psF32           airmass;
    psF64           ra;
    psF64           decl;
    psF32           exp_time;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF64           alt;
    psF64           az;
    psF32           ccd_temp;
    psF64           posang;
    char            *object;
    psTime*         dateobs;
    psS16           fault;
} rawImfileRow;

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

rawImfileRow *rawImfileRowAlloc(
    const char      *exp_tag,
    const char      *class,
    const char      *class_id,
    const char      *uri,
    const char      *exp_type,
    const char      *filter,
    psF32           airmass,
    psF64           ra,
    psF64           decl,
    psF32           exp_time,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           alt,
    psF64           az,
    psF32           ccd_temp,
    psF64           posang,
    const char      *object,
    psTime*         dateobs,
    psS16           fault
);

/** 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
    const char      *exp_tag,
    const char      *class,
    const char      *class_id,
    const char      *uri,
    const char      *exp_type,
    const char      *filter,
    psF32           airmass,
    psF64           ra,
    psF64           decl,
    psF32           exp_time,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF64           alt,
    psF64           az,
    psF32           ccd_temp,
    psF64           posang,
    const char      *object,
    psTime*         dateobs,
    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 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
);
/** p1PendingExpRow data structure
 *
 * Structure for representing a single row of p1PendingExp table data.
 */

typedef struct {
    char            *exp_tag;
    char            *recipe;
    psS32           p1_version;
} p1PendingExpRow;

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

p1PendingExpRow *p1PendingExpRowAlloc(
    const char      *exp_tag,
    const char      *recipe,
    psS32           p1_version
);

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

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

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

bool p1PendingExpDropTable(
    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 p1PendingExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_tag,
    const char      *recipe,
    psS32           p1_version
);

/** 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 p1PendingExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p1PendingExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p1PendingExpRow *object             ///< p1PendingExpRow object
);

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

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

/** Insert data from a binary FITS table p1PendingExpRow 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 p1PendingExpInsertFits(
    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 p1PendingExpSelectRowsFits(
    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 p1PendingExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p1PendingExpMetadataFromObject(
    const p1PendingExpRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p1PendingExpSelectRowObjects(
    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 p1PendingExp
 *
 *  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 p1PendingExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p1PendingExpRow *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 p1PendingExpDeleteRowObjects(
    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 p1PendingExpRow 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 p1PendingExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p1PendingExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p1PendingExpRow 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 p1PendingExpPrintObject(
    FILE            *stream,            ///< a stream
    p1PendingExpRow *object,    ///< an p1PendingExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p2PendingExpRow data structure
 *
 * Structure for representing a single row of p2PendingExp table data.
 */

typedef struct {
    char            *exp_tag;
    char            *recipe;
    psS32           p1_version;
    psS32           p2_version;
    char            *label;
} p2PendingExpRow;

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

p2PendingExpRow *p2PendingExpRowAlloc(
    const char      *exp_tag,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version,
    const char      *label
);

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

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

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

bool p2PendingExpDropTable(
    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 p2PendingExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_tag,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version,
    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 p2PendingExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p2PendingExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p2PendingExpRow *object             ///< p2PendingExpRow object
);

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

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

/** Insert data from a binary FITS table p2PendingExpRow 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 p2PendingExpInsertFits(
    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 p2PendingExpSelectRowsFits(
    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 p2PendingExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p2PendingExpMetadataFromObject(
    const p2PendingExpRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p2PendingExpSelectRowObjects(
    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 p2PendingExp
 *
 *  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 p2PendingExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p2PendingExpRow *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 p2PendingExpDeleteRowObjects(
    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 p2PendingExpRow 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 p2PendingExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p2PendingExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p2PendingExpRow 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 p2PendingExpPrintObject(
    FILE            *stream,            ///< a stream
    p2PendingExpRow *object,    ///< an p2PendingExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p2PendingImfileRow data structure
 *
 * Structure for representing a single row of p2PendingImfile table data.
 */

typedef struct {
    char            *exp_tag;
    char            *class_id;
    char            *uri;
    char            *recipe;
    psS32           p1_version;
    psS32           p2_version;
} p2PendingImfileRow;

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

p2PendingImfileRow *p2PendingImfileRowAlloc(
    const char      *exp_tag,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

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

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

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

bool p2PendingImfileDropTable(
    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 p2PendingImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_tag,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

/** 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 p2PendingImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p2PendingImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    p2PendingImfileRow *object             ///< p2PendingImfileRow object
);

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

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

/** Insert data from a binary FITS table p2PendingImfileRow 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 p2PendingImfileInsertFits(
    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 p2PendingImfileSelectRowsFits(
    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 p2PendingImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p2PendingImfileMetadataFromObject(
    const p2PendingImfileRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p2PendingImfileSelectRowObjects(
    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 p2PendingImfile
 *
 *  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 p2PendingImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p2PendingImfileRow *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 p2PendingImfileDeleteRowObjects(
    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 p2PendingImfileRow 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 p2PendingImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p2PendingImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p2PendingImfileRow 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 p2PendingImfilePrintObject(
    FILE            *stream,            ///< a stream
    p2PendingImfileRow *object,    ///< an p2PendingImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p2ProcessedExpRow data structure
 *
 * Structure for representing a single row of p2ProcessedExp table data.
 */

typedef struct {
    char            *exp_tag;
    psS32           p1_version;
    psS32           p2_version;
    char            *label;
} p2ProcessedExpRow;

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

p2ProcessedExpRow *p2ProcessedExpRowAlloc(
    const char      *exp_tag,
    psS32           p1_version,
    psS32           p2_version,
    const char      *label
);

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

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

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

bool p2ProcessedExpDropTable(
    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 p2ProcessedExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_tag,
    psS32           p1_version,
    psS32           p2_version,
    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 p2ProcessedExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p2ProcessedExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p2ProcessedExpRow *object             ///< p2ProcessedExpRow object
);

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

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

/** Insert data from a binary FITS table p2ProcessedExpRow 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 p2ProcessedExpInsertFits(
    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 p2ProcessedExpSelectRowsFits(
    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 p2ProcessedExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p2ProcessedExpMetadataFromObject(
    const p2ProcessedExpRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p2ProcessedExpSelectRowObjects(
    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 p2ProcessedExp
 *
 *  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 p2ProcessedExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p2ProcessedExpRow *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 p2ProcessedExpDeleteRowObjects(
    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 p2ProcessedExpRow 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 p2ProcessedExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p2ProcessedExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p2ProcessedExpRow 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 p2ProcessedExpPrintObject(
    FILE            *stream,            ///< a stream
    p2ProcessedExpRow *object,    ///< an p2ProcessedExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p2MaskRow data structure
 *
 * Structure for representing a single row of p2Mask table data.
 */

typedef struct {
    char            *label;
} p2MaskRow;

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

p2MaskRow *p2MaskRowAlloc(
    const char      *label
);

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

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

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

bool p2MaskDropTable(
    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 p2MaskInsert(
    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 p2MaskDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p2MaskInsertObject(
    psDB            *dbh,               ///< Database handle
    p2MaskRow       *object             ///< p2MaskRow object
);

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

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

/** Insert data from a binary FITS table p2MaskRow 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 p2MaskInsertFits(
    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 p2MaskSelectRowsFits(
    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 p2MaskRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p2MaskMetadataFromObject(
    const p2MaskRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p2MaskSelectRowObjects(
    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 p2Mask
 *
 *  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 p2MaskDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p2MaskRow *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 p2MaskDeleteRowObjects(
    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 p2MaskRow 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 p2MaskPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p2MaskRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p2MaskRow 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 p2MaskPrintObject(
    FILE            *stream,            ///< a stream
    p2MaskRow *object,    ///< an p2MaskRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p2ProcessedImfileRow data structure
 *
 * Structure for representing a single row of p2ProcessedImfile table data.
 */

typedef struct {
    char            *exp_tag;
    char            *class_id;
    char            *uri;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    char            *b1_uri;
    char            *b2_uri;
    psS32           p1_version;
    psS32           p2_version;
    psS16           fault;
} p2ProcessedImfileRow;

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

p2ProcessedImfileRow *p2ProcessedImfileRowAlloc(
    const char      *exp_tag,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_uri,
    psS32           p1_version,
    psS32           p2_version,
    psS16           fault
);

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

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

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

bool p2ProcessedImfileDropTable(
    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 p2ProcessedImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_tag,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_uri,
    psS32           p1_version,
    psS32           p2_version,
    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 p2ProcessedImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p2ProcessedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    p2ProcessedImfileRow *object             ///< p2ProcessedImfileRow object
);

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

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

/** Insert data from a binary FITS table p2ProcessedImfileRow 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 p2ProcessedImfileInsertFits(
    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 p2ProcessedImfileSelectRowsFits(
    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 p2ProcessedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p2ProcessedImfileMetadataFromObject(
    const p2ProcessedImfileRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p2ProcessedImfileSelectRowObjects(
    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 p2ProcessedImfile
 *
 *  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 p2ProcessedImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p2ProcessedImfileRow *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 p2ProcessedImfileDeleteRowObjects(
    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 p2ProcessedImfileRow 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 p2ProcessedImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p2ProcessedImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p2ProcessedImfileRow 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 p2ProcessedImfilePrintObject(
    FILE            *stream,            ///< a stream
    p2ProcessedImfileRow *object,    ///< an p2ProcessedImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p3PendingExpRow data structure
 *
 * Structure for representing a single row of p3PendingExp table data.
 */

typedef struct {
    char            *exp_tag;
    psS32           p2_version;
    psS32           p3_version;
    char            *label;
} p3PendingExpRow;

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

p3PendingExpRow *p3PendingExpRowAlloc(
    const char      *exp_tag,
    psS32           p2_version,
    psS32           p3_version,
    const char      *label
);

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

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

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

bool p3PendingExpDropTable(
    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 p3PendingExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_tag,
    psS32           p2_version,
    psS32           p3_version,
    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 p3PendingExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p3PendingExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p3PendingExpRow *object             ///< p3PendingExpRow object
);

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

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

/** Insert data from a binary FITS table p3PendingExpRow 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 p3PendingExpInsertFits(
    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 p3PendingExpSelectRowsFits(
    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 p3PendingExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p3PendingExpMetadataFromObject(
    const p3PendingExpRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p3PendingExpSelectRowObjects(
    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 p3PendingExp
 *
 *  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 p3PendingExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p3PendingExpRow *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 p3PendingExpDeleteRowObjects(
    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 p3PendingExpRow 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 p3PendingExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p3PendingExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p3PendingExpRow 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 p3PendingExpPrintObject(
    FILE            *stream,            ///< a stream
    p3PendingExpRow *object,    ///< an p3PendingExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p3ProcessedExpRow data structure
 *
 * Structure for representing a single row of p3ProcessedExp table data.
 */

typedef struct {
    char            *exp_tag;
    char            *uri;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psF32           sigma_ra;
    psF32           sigma_dec;
    psS32           nastro;
    char            *b1_uri;
    char            *b2_uri;
    psF32           zp_mean;
    psF32           zp_stdev;
    psS32           p2_version;
    psS32           p3_version;
    char            *label;
    psS16           fault;
} p3ProcessedExpRow;

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

p3ProcessedExpRow *p3ProcessedExpRowAlloc(
    const char      *exp_tag,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF32           sigma_ra,
    psF32           sigma_dec,
    psS32           nastro,
    const char      *b1_uri,
    const char      *b2_uri,
    psF32           zp_mean,
    psF32           zp_stdev,
    psS32           p2_version,
    psS32           p3_version,
    const char      *label,
    psS16           fault
);

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

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

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

bool p3ProcessedExpDropTable(
    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 p3ProcessedExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_tag,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    psF32           sigma_ra,
    psF32           sigma_dec,
    psS32           nastro,
    const char      *b1_uri,
    const char      *b2_uri,
    psF32           zp_mean,
    psF32           zp_stdev,
    psS32           p2_version,
    psS32           p3_version,
    const char      *label,
    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 p3ProcessedExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p3ProcessedExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p3ProcessedExpRow *object             ///< p3ProcessedExpRow object
);

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

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

/** Insert data from a binary FITS table p3ProcessedExpRow 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 p3ProcessedExpInsertFits(
    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 p3ProcessedExpSelectRowsFits(
    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 p3ProcessedExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p3ProcessedExpMetadataFromObject(
    const p3ProcessedExpRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p3ProcessedExpSelectRowObjects(
    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 p3ProcessedExp
 *
 *  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 p3ProcessedExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p3ProcessedExpRow *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 p3ProcessedExpDeleteRowObjects(
    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 p3ProcessedExpRow 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 p3ProcessedExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p3ProcessedExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p3ProcessedExpRow 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 p3ProcessedExpPrintObject(
    FILE            *stream,            ///< a stream
    p3ProcessedExpRow *object,    ///< an p3ProcessedExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p3MaskRow data structure
 *
 * Structure for representing a single row of p3Mask table data.
 */

typedef struct {
    char            *label;
} p3MaskRow;

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

p3MaskRow *p3MaskRowAlloc(
    const char      *label
);

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

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

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

bool p3MaskDropTable(
    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 p3MaskInsert(
    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 p3MaskDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p3MaskInsertObject(
    psDB            *dbh,               ///< Database handle
    p3MaskRow       *object             ///< p3MaskRow object
);

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

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

/** Insert data from a binary FITS table p3MaskRow 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 p3MaskInsertFits(
    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 p3MaskSelectRowsFits(
    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 p3MaskRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p3MaskMetadataFromObject(
    const p3MaskRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p3MaskSelectRowObjects(
    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 p3Mask
 *
 *  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 p3MaskDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p3MaskRow *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 p3MaskDeleteRowObjects(
    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 p3MaskRow 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 p3MaskPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p3MaskRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p3MaskRow 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 p3MaskPrintObject(
    FILE            *stream,            ///< a stream
    p3MaskRow *object,    ///< an p3MaskRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** detRunRow data structure
 *
 * Structure for representing a single row of detRun table data.
 */

typedef struct {
    psS32           det_id;
    psS32           iteration;
    char            *det_type;
    char            *mode;
    char            *state;
    char            *workdir;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    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;
} detRunRow;

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

detRunRow *detRunRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *det_type,
    const char      *mode,
    const char      *state,
    const char      *workdir,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    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
);

/** 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
    psS32           det_id,
    psS32           iteration,
    const char      *det_type,
    const char      *mode,
    const char      *state,
    const char      *workdir,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    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
);

/** 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 {
    psS32           det_id;
    psS32           iteration;
    char            *exp_tag;
    bool            include;
} detInputExpRow;

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

detInputExpRow *detInputExpRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *exp_tag,
    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
    psS32           det_id,
    psS32           iteration,
    const char      *exp_tag,
    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 {
    psS32           det_id;
    char            *exp_tag;
    char            *class_id;
    char            *uri;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    char            *b1_uri;
    char            *b2_uri;
    psS16           fault;
} detProcessedImfileRow;

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

detProcessedImfileRow *detProcessedImfileRowAlloc(
    psS32           det_id,
    const char      *exp_tag,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_uri,
    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
    psS32           det_id,
    const char      *exp_tag,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_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 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 {
    psS32           det_id;
    char            *exp_tag;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    char            *b1_uri;
    char            *b2_uri;
    psS16           fault;
} detProcessedExpRow;

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

detProcessedExpRow *detProcessedExpRowAlloc(
    psS32           det_id,
    const char      *exp_tag,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_uri,
    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
    psS32           det_id,
    const char      *exp_tag,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_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 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 {
    psS32           det_id;
    psS32           iteration;
    char            *class_id;
    char            *uri;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    psS16           fault;
} detStackedImfileRow;

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

detStackedImfileRow *detStackedImfileRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    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
    psS32           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    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 {
    psS32           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(
    psS32           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
    psS32           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 {
    psS32           det_id;
    psS32           iteration;
    char            *class_id;
    char            *uri;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    char            *b1_uri;
    char            *b2_uri;
    psS16           fault;
} detNormalizedImfileRow;

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

detNormalizedImfileRow *detNormalizedImfileRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_uri,
    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
    psS32           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_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 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 {
    psS32           det_id;
    psS32           iteration;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    char            *b1_uri;
    char            *b2_uri;
    psS16           fault;
} detNormalizedExpRow;

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

detNormalizedExpRow *detNormalizedExpRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_uri,
    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
    psS32           det_id,
    psS32           iteration,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_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 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 {
    psS32           det_id;
    psS32           iteration;
    char            *exp_tag;
    char            *class_id;
    char            *uri;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    char            *b1_uri;
    char            *b2_uri;
    psS16           fault;
} detResidImfileRow;

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

detResidImfileRow *detResidImfileRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *exp_tag,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_uri,
    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
    psS32           det_id,
    psS32           iteration,
    const char      *exp_tag,
    const char      *class_id,
    const char      *uri,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_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 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 {
    psS32           det_id;
    psS32           iteration;
    char            *exp_tag;
    char            *recipe;
    psF64           bg;
    psF64           bg_stdev;
    psF64           bg_mean_stdev;
    char            *b1_uri;
    char            *b2_uri;
    bool            accept;
    psS16           fault;
} detResidExpRow;

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

detResidExpRow *detResidExpRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *exp_tag,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_uri,
    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
    psS32           det_id,
    psS32           iteration,
    const char      *exp_tag,
    const char      *recipe,
    psF64           bg,
    psF64           bg_stdev,
    psF64           bg_mean_stdev,
    const char      *b1_uri,
    const char      *b2_uri,
    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 {
    psS32           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(
    psS32           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
    psS32           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
);
/** p4aRunRow data structure
 *
 * Structure for representing a single row of p4aRun table data.
 */

typedef struct {
    psS32           p4a_id;
    char            *state;
    char            *workdir;
    bool            magic;
} p4aRunRow;

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

p4aRunRow *p4aRunRowAlloc(
    psS32           p4a_id,
    const char      *state,
    const char      *workdir,
    bool            magic
);

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

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

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

bool p4aRunDropTable(
    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 p4aRunInsert(
    psDB            *dbh,               ///< Database handle
    psS32           p4a_id,
    const char      *state,
    const char      *workdir,
    bool            magic
);

/** 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 p4aRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p4aRunInsertObject(
    psDB            *dbh,               ///< Database handle
    p4aRunRow       *object             ///< p4aRunRow object
);

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

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

/** Insert data from a binary FITS table p4aRunRow 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 p4aRunInsertFits(
    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 p4aRunSelectRowsFits(
    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 p4aRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p4aRunMetadataFromObject(
    const p4aRunRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p4aRunSelectRowObjects(
    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 p4aRun
 *
 *  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 p4aRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p4aRunRow *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 p4aRunDeleteRowObjects(
    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 p4aRunRow 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 p4aRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p4aRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p4aRunRow 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 p4aRunPrintObject(
    FILE            *stream,            ///< a stream
    p4aRunRow *object,    ///< an p4aRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p4aInputExpRow data structure
 *
 * Structure for representing a single row of p4aInputExp table data.
 */

typedef struct {
    psS32           p4a_id;
    char            *exp_tag;
    psS32           p3_version;
} p4aInputExpRow;

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

p4aInputExpRow *p4aInputExpRowAlloc(
    psS32           p4a_id,
    const char      *exp_tag,
    psS32           p3_version
);

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

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

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

bool p4aInputExpDropTable(
    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 p4aInputExpInsert(
    psDB            *dbh,               ///< Database handle
    psS32           p4a_id,
    const char      *exp_tag,
    psS32           p3_version
);

/** 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 p4aInputExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p4aInputExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p4aInputExpRow  *object             ///< p4aInputExpRow object
);

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

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

/** Insert data from a binary FITS table p4aInputExpRow 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 p4aInputExpInsertFits(
    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 p4aInputExpSelectRowsFits(
    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 p4aInputExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p4aInputExpMetadataFromObject(
    const p4aInputExpRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p4aInputExpSelectRowObjects(
    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 p4aInputExp
 *
 *  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 p4aInputExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p4aInputExpRow *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 p4aInputExpDeleteRowObjects(
    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 p4aInputExpRow 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 p4aInputExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p4aInputExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p4aInputExpRow 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 p4aInputExpPrintObject(
    FILE            *stream,            ///< a stream
    p4aInputExpRow *object,    ///< an p4aInputExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p4aScfileRow data structure
 *
 * Structure for representing a single row of p4aScfile table data.
 */

typedef struct {
    psS32           p4a_id;
    char            *skycell_id;
    char            *tess_id;
    char            *exp_tag;
    psS32           p3_version;
    char            *uri;
    psF64           bg;
    psF64           bg_mean_stdev;
} p4aScfileRow;

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

p4aScfileRow *p4aScfileRowAlloc(
    psS32           p4a_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *exp_tag,
    psS32           p3_version,
    const char      *uri,
    psF64           bg,
    psF64           bg_mean_stdev
);

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

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

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

bool p4aScfileDropTable(
    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 p4aScfileInsert(
    psDB            *dbh,               ///< Database handle
    psS32           p4a_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *exp_tag,
    psS32           p3_version,
    const char      *uri,
    psF64           bg,
    psF64           bg_mean_stdev
);

/** 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 p4aScfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p4aScfileInsertObject(
    psDB            *dbh,               ///< Database handle
    p4aScfileRow    *object             ///< p4aScfileRow object
);

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

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

/** Insert data from a binary FITS table p4aScfileRow 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 p4aScfileInsertFits(
    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 p4aScfileSelectRowsFits(
    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 p4aScfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p4aScfileMetadataFromObject(
    const p4aScfileRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p4aScfileSelectRowObjects(
    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 p4aScfile
 *
 *  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 p4aScfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p4aScfileRow *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 p4aScfileDeleteRowObjects(
    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 p4aScfileRow 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 p4aScfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p4aScfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p4aScfileRow 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 p4aScfilePrintObject(
    FILE            *stream,            ///< a stream
    p4aScfileRow *object,    ///< an p4aScfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p4bRunRow data structure
 *
 * Structure for representing a single row of p4bRun table data.
 */

typedef struct {
    psS32           p4b_id;
    char            *state;
    char            *workdir;
    bool            magic;
} p4bRunRow;

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

p4bRunRow *p4bRunRowAlloc(
    psS32           p4b_id,
    const char      *state,
    const char      *workdir,
    bool            magic
);

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

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

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

bool p4bRunDropTable(
    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 p4bRunInsert(
    psDB            *dbh,               ///< Database handle
    psS32           p4b_id,
    const char      *state,
    const char      *workdir,
    bool            magic
);

/** 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 p4bRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p4bRunInsertObject(
    psDB            *dbh,               ///< Database handle
    p4bRunRow       *object             ///< p4bRunRow object
);

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

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

/** Insert data from a binary FITS table p4bRunRow 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 p4bRunInsertFits(
    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 p4bRunSelectRowsFits(
    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 p4bRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p4bRunMetadataFromObject(
    const p4bRunRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p4bRunSelectRowObjects(
    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 p4bRun
 *
 *  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 p4bRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p4bRunRow *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 p4bRunDeleteRowObjects(
    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 p4bRunRow 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 p4bRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p4bRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p4bRunRow 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 p4bRunPrintObject(
    FILE            *stream,            ///< a stream
    p4bRunRow *object,    ///< an p4bRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p4bInputScfileRow data structure
 *
 * Structure for representing a single row of p4bInputScfile table data.
 */

typedef struct {
    psS32           p4b_id;
    char            *skycell_id;
    char            *tess_id;
    char            *exp_tag;
    psS32           p3_version;
    char            *kind;
} p4bInputScfileRow;

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

p4bInputScfileRow *p4bInputScfileRowAlloc(
    psS32           p4b_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *exp_tag,
    psS32           p3_version,
    const char      *kind
);

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

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

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

bool p4bInputScfileDropTable(
    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 p4bInputScfileInsert(
    psDB            *dbh,               ///< Database handle
    psS32           p4b_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *exp_tag,
    psS32           p3_version,
    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 p4bInputScfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p4bInputScfileInsertObject(
    psDB            *dbh,               ///< Database handle
    p4bInputScfileRow *object             ///< p4bInputScfileRow object
);

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

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

/** Insert data from a binary FITS table p4bInputScfileRow 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 p4bInputScfileInsertFits(
    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 p4bInputScfileSelectRowsFits(
    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 p4bInputScfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p4bInputScfileMetadataFromObject(
    const p4bInputScfileRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p4bInputScfileSelectRowObjects(
    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 p4bInputScfile
 *
 *  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 p4bInputScfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p4bInputScfileRow *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 p4bInputScfileDeleteRowObjects(
    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 p4bInputScfileRow 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 p4bInputScfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p4bInputScfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p4bInputScfileRow 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 p4bInputScfilePrintObject(
    FILE            *stream,            ///< a stream
    p4bInputScfileRow *object,    ///< an p4bInputScfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p4bDiffScfileRow data structure
 *
 * Structure for representing a single row of p4bDiffScfile table data.
 */

typedef struct {
    psS32           p4b_id;
    char            *skycell_id;
    char            *tess_id;
    char            *exp_tag;
    psS32           p3_version;
    char            *uri;
    psF64           bg;
    psF64           bg_mean_stdev;
} p4bDiffScfileRow;

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

p4bDiffScfileRow *p4bDiffScfileRowAlloc(
    psS32           p4b_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *exp_tag,
    psS32           p3_version,
    const char      *uri,
    psF64           bg,
    psF64           bg_mean_stdev
);

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

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

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

bool p4bDiffScfileDropTable(
    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 p4bDiffScfileInsert(
    psDB            *dbh,               ///< Database handle
    psS32           p4b_id,
    const char      *skycell_id,
    const char      *tess_id,
    const char      *exp_tag,
    psS32           p3_version,
    const char      *uri,
    psF64           bg,
    psF64           bg_mean_stdev
);

/** 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 p4bDiffScfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p4bDiffScfileInsertObject(
    psDB            *dbh,               ///< Database handle
    p4bDiffScfileRow *object             ///< p4bDiffScfileRow object
);

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

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

/** Insert data from a binary FITS table p4bDiffScfileRow 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 p4bDiffScfileInsertFits(
    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 p4bDiffScfileSelectRowsFits(
    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 p4bDiffScfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p4bDiffScfileMetadataFromObject(
    const p4bDiffScfileRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p4bDiffScfileSelectRowObjects(
    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 p4bDiffScfile
 *
 *  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 p4bDiffScfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p4bDiffScfileRow *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 p4bDiffScfileDeleteRowObjects(
    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 p4bDiffScfileRow 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 p4bDiffScfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p4bDiffScfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p4bDiffScfileRow 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 p4bDiffScfilePrintObject(
    FILE            *stream,            ///< a stream
    p4bDiffScfileRow *object,    ///< an p4bDiffScfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p4cRunRow data structure
 *
 * Structure for representing a single row of p4cRun table data.
 */

typedef struct {
    psS32           p4c_id;
    char            *state;
    char            *workdir;
    bool            magic;
} p4cRunRow;

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

p4cRunRow *p4cRunRowAlloc(
    psS32           p4c_id,
    const char      *state,
    const char      *workdir,
    bool            magic
);

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

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

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

bool p4cRunDropTable(
    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 p4cRunInsert(
    psDB            *dbh,               ///< Database handle
    psS32           p4c_id,
    const char      *state,
    const char      *workdir,
    bool            magic
);

/** 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 p4cRunDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p4cRunInsertObject(
    psDB            *dbh,               ///< Database handle
    p4cRunRow       *object             ///< p4cRunRow object
);

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

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

/** Insert data from a binary FITS table p4cRunRow 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 p4cRunInsertFits(
    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 p4cRunSelectRowsFits(
    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 p4cRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p4cRunMetadataFromObject(
    const p4cRunRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p4cRunSelectRowObjects(
    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 p4cRun
 *
 *  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 p4cRunDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p4cRunRow *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 p4cRunDeleteRowObjects(
    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 p4cRunRow 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 p4cRunPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p4cRunRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p4cRunRow 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 p4cRunPrintObject(
    FILE            *stream,            ///< a stream
    p4cRunRow *object,    ///< an p4cRunRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p4cInputExpRow data structure
 *
 * Structure for representing a single row of p4cInputExp table data.
 */

typedef struct {
    psS32           p4c_id;
    char            *exp_tag;
    psS32           p3_version;
} p4cInputExpRow;

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

p4cInputExpRow *p4cInputExpRowAlloc(
    psS32           p4c_id,
    const char      *exp_tag,
    psS32           p3_version
);

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

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

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

bool p4cInputExpDropTable(
    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 p4cInputExpInsert(
    psDB            *dbh,               ///< Database handle
    psS32           p4c_id,
    const char      *exp_tag,
    psS32           p3_version
);

/** 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 p4cInputExpDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p4cInputExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p4cInputExpRow  *object             ///< p4cInputExpRow object
);

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

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

/** Insert data from a binary FITS table p4cInputExpRow 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 p4cInputExpInsertFits(
    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 p4cInputExpSelectRowsFits(
    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 p4cInputExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p4cInputExpMetadataFromObject(
    const p4cInputExpRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p4cInputExpSelectRowObjects(
    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 p4cInputExp
 *
 *  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 p4cInputExpDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p4cInputExpRow *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 p4cInputExpDeleteRowObjects(
    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 p4cInputExpRow 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 p4cInputExpPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p4cInputExpRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p4cInputExpRow 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 p4cInputExpPrintObject(
    FILE            *stream,            ///< a stream
    p4cInputExpRow *object,    ///< an p4cInputExpRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** p4MagicMaskImfileRow data structure
 *
 * Structure for representing a single row of p4MagicMaskImfile table data.
 */

typedef struct {
    psS32           p4c_id;
    char            *exp_tag;
    psS32           p3_version;
    char            *class_id;
    char            *uri;
} p4MagicMaskImfileRow;

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

p4MagicMaskImfileRow *p4MagicMaskImfileRowAlloc(
    psS32           p4c_id,
    const char      *exp_tag,
    psS32           p3_version,
    const char      *class_id,
    const char      *uri
);

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

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

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

bool p4MagicMaskImfileDropTable(
    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 p4MagicMaskImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS32           p4c_id,
    const char      *exp_tag,
    psS32           p3_version,
    const char      *class_id,
    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 p4MagicMaskImfileDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool p4MagicMaskImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    p4MagicMaskImfileRow *object             ///< p4MagicMaskImfileRow object
);

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

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

/** Insert data from a binary FITS table p4MagicMaskImfileRow 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 p4MagicMaskImfileInsertFits(
    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 p4MagicMaskImfileSelectRowsFits(
    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 p4MagicMaskImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p4MagicMaskImfileMetadataFromObject(
    const p4MagicMaskImfileRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *p4MagicMaskImfileSelectRowObjects(
    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 p4MagicMaskImfile
 *
 *  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 p4MagicMaskImfileDeleteObject(
    psDB            *dbh,               ///< Database handle
    const p4MagicMaskImfileRow *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 p4MagicMaskImfileDeleteRowObjects(
    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 p4MagicMaskImfileRow 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 p4MagicMaskImfilePrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of p4MagicMaskImfileRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an p4MagicMaskImfileRow 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 p4MagicMaskImfilePrintObject(
    FILE            *stream,            ///< a stream
    p4MagicMaskImfileRow *object,    ///< an p4MagicMaskImfileRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** skyCellRow data structure
 *
 * Structure for representing a single row of skyCell table data.
 */

typedef struct {
    char            *skycell_id;
    char            *tess_id;
    psF64           ra1;
    psF64           decl1;
    psF64           ra2;
    psF64           decl2;
    psF64           ra3;
    psF64           decl3;
    psF64           ra4;
    psF64           decl4;
} skyCellRow;

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

skyCellRow *skyCellRowAlloc(
    const char      *skycell_id,
    const char      *tess_id,
    psF64           ra1,
    psF64           decl1,
    psF64           ra2,
    psF64           decl2,
    psF64           ra3,
    psF64           decl3,
    psF64           ra4,
    psF64           decl4
);

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

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

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

bool skyCellDropTable(
    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 skyCellInsert(
    psDB            *dbh,               ///< Database handle
    const char      *skycell_id,
    const char      *tess_id,
    psF64           ra1,
    psF64           decl1,
    psF64           ra2,
    psF64           decl2,
    psF64           ra3,
    psF64           decl3,
    psF64           ra4,
    psF64           decl4
);

/** 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 skyCellDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool skyCellInsertObject(
    psDB            *dbh,               ///< Database handle
    skyCellRow      *object             ///< skyCellRow object
);

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

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

/** Insert data from a binary FITS table skyCellRow 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 skyCellInsertFits(
    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 skyCellSelectRowsFits(
    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 skyCellRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *skyCellMetadataFromObject(
    const skyCellRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *skyCellSelectRowObjects(
    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 skyCell
 *
 *  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 skyCellDeleteObject(
    psDB            *dbh,               ///< Database handle
    const skyCellRow *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 skyCellDeleteRowObjects(
    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 skyCellRow 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 skyCellPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of skyCellRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an skyCellRow 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 skyCellPrintObject(
    FILE            *stream,            ///< a stream
    skyCellRow *object,    ///< an skyCellRow object
    bool            mdcf                ///< format as mdconfig or simple
);
/** skyCellMapRow data structure
 *
 * Structure for representing a single row of skyCellMap table data.
 */

typedef struct {
    char            *skycell_id;
    char            *tess_id;
    char            *exp_tag;
    char            *class_id;
} skyCellMapRow;

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

skyCellMapRow *skyCellMapRowAlloc(
    const char      *skycell_id,
    const char      *tess_id,
    const char      *exp_tag,
    const char      *class_id
);

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

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

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

bool skyCellMapDropTable(
    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 skyCellMapInsert(
    psDB            *dbh,               ///< Database handle
    const char      *skycell_id,
    const char      *tess_id,
    const char      *exp_tag,
    const char      *class_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 skyCellMapDelete(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to delete 
);

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

bool skyCellMapInsertObject(
    psDB            *dbh,               ///< Database handle
    skyCellMapRow   *object             ///< skyCellMapRow object
);

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

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

/** Insert data from a binary FITS table skyCellMapRow 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 skyCellMapInsertFits(
    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 skyCellMapSelectRowsFits(
    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 skyCellMapRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *skyCellMapMetadataFromObject(
    const skyCellMapRow *object             ///< fooRow to convert into a psMetadata
);

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

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

psArray *skyCellMapSelectRowObjects(
    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 skyCellMap
 *
 *  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 skyCellMapDeleteObject(
    psDB            *dbh,               ///< Database handle
    const skyCellMapRow *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 skyCellMapDeleteRowObjects(
    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 skyCellMapRow 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 skyCellMapPrintObjects(
    FILE            *stream,            ///< a stream
    psArray         *objects,           ///< An array of skyCellMapRow objects
    bool            mdcf                ///< format as mdconfig or simple
);
/** Formats and prints an skyCellMapRow 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 skyCellMapPrintObject(
    FILE            *stream,            ///< a stream
    skyCellMapRow *object,    ///< an skyCellMapRow object
    bool            mdcf                ///< format as mdconfig or simple
);

/// @}

#ifdef __cplusplus
}
#endif

#endif // SKYCELLMAP_DB_H
