/* SDB - import/export command routines */

#include "stdio.h"
#include "sdbio.h"

extern int dbv_token;
extern char dbv_tstring[];
extern int dbv_tvalue;

/* db_import - import tuples from a file */
int *db_import(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  char *fmt;
{
    struct scan *sptr;
    struct attribute *aptr;
    char fname[STRINGMAX+1],avalue[STRINGMAX+1];
    int tcnt,astart,i,eofile;
    FILE *fp;

    /* check for a command line */
    if (fmt != NULL)
        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

    /* checks for "<filename> into <relation-name>" */
    if (db_ntoken() == ID)
        strcat(dbv_tstring,".dat");
    else if (dbv_token != STRING)
        return (db_ferror(SYNTAX));
    strcpy(fname,dbv_tstring);
    if (db_ntoken() != INTO)
        return (db_ferror(SYNTAX));
    if (db_ntoken() != ID)
        return (db_ferror(SYNTAX));

    /* open the relation */
    if ((sptr = db_ropen(dbv_tstring)) == NULL)
        return (FALSE);

    /* open the input file */
    if ((fp = fopen(fname,"r")) == NULL)
        return (db_ferror(INPFNF));

    /* import tuples */
    eofile = FALSE;
    for (tcnt = 0; ; tcnt++) {

        /* get attribute values */
        astart = 1;
        for (i = 0; i < NATTRS; i++) {

            /* get a pointer to the current attribute */
            aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

            /* check for the last attribute */
            if (aptr->at_name[0] == 0)
                break;

            /* input the tuple */
            if (fgets(avalue,STRINGMAX,fp) == 0) {
                eofile = TRUE;
                break;
            }
            avalue[strlen(avalue)-1] = EOS;

            /* store the attribute value */
            db_aput(aptr,&sptr->sc_tuple[astart],avalue);

            /* update the attribute start */
            astart += aptr->at_size;
        }

        /* store the new tuple */
        if (!eofile) {
            if (!db_rstore(sptr)) {
                db_rclose(sptr);
                return (FALSE);
            }
        }
        else
            break;
    }

    /* close the relation */
    db_rclose(sptr);

    /* close the input file */
    fclose(fp);

    /* check number of tuples imported */
    if (tcnt != 0) {

        /* print tuple count */
        printf("[ %d imported ]\n",tcnt);
    }
    else
        printf("[ none imported ]\n");

    /* return successfully */
    return (TRUE);
}

/* db_export - export tuples to a file */
int *db_export(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  char *fmt;
{
    struct scan *sptr;
    struct attribute *aptr;
    char rname[STRINGMAX+1],avalue[STRINGMAX+1];
    int tcnt,astart,i;
    FILE *fp;

    /* check for a command line */
    if (fmt != NULL)
        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

    /* checks for "<relation-name> [ into <filename> ]" */
    if (db_ntoken() != ID)
        return (db_ferror(SYNTAX));
    strcpy(rname,dbv_tstring);
    if (!db_to(&fp,".dat"))
        return (FALSE);

    /* open the relation */
    if ((sptr = db_ropen(rname)) == NULL)
        return (FALSE);

    /* export tuples */
    for (tcnt = 0; db_rfetch(sptr); tcnt++) {

        /* get attribute values */
        astart = 1;
        for (i = 0; i < NATTRS; i++) {

            /* get a pointer to the current attribute */
            aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

            /* check for the last attribute */
            if (aptr->at_name[0] == 0)
                break;

            /* get the attribute value */
            db_aget(aptr,&sptr->sc_tuple[astart],avalue);

            /* output the tuple */
            fprintf(fp,"%s\n",avalue);

            /* update the attribute start */
            astart += aptr->at_size;
        }
    }

    /* close the relation */
    db_rclose(sptr);

    /* close the output file */
    if (fp != stdout)
        fclose(fp);

    /* check number of tuples exported */
    if (tcnt != 0) {

        /* print tuple count */
        printf("[ %d exported ]\n",tcnt);
    }
    else
        printf("[ none exported ]\n");

    /* return successfully */
    return (TRUE);
}

/* db_squeeze - squeeze deleted tuples from a relation file */
int *db_squeeze(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  char *fmt;
{
    struct scan *sptr;

    /* check for a command line */
    if (fmt != NULL)
        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

    /* checks for "<relation-name>" */
    if (db_ntoken() != ID)
        return (db_ferror(SYNTAX));

    /* open the relation */
    if ((sptr = db_ropen(dbv_tstring)) == NULL)
        return (FALSE);

    /* compress the relation file */
    if (!db_rcompress(sptr)) {
        db_rclose(sptr);
        return (FALSE);
    }

    /* close the relation */
    db_rclose(sptr);

    /* return successfully */
    return (TRUE);
}

/* db_extract - extract a relation definition */
int *db_extract(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  char *fmt;
{
    struct scan *sptr;
    struct attribute *aptr;
    char rname[STRINGMAX+1],aname[ANSIZE+1],*atype;
    int i;
    FILE *fp;

    /* check for a command line */
    if (fmt != NULL)
        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

    /* checks for "<relation-name> [ into <filename> ]" */
    if (db_ntoken() != ID)
        return (db_ferror(SYNTAX));
    strcpy(rname,dbv_tstring);
    if (!db_to(&fp,".def"))
        return (FALSE);

    /* open the relation */
    if ((sptr = db_ropen(rname)) == NULL)
        return (FALSE);

    /* output the relation definition */
    fprintf(fp,"create %s (\n",rname);

    /* get attribute values */
    for (i = 0; i < NATTRS; i++) {

        /* get a pointer to the current attribute */
        aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

        /* check for the last attribute */
        if (aptr->at_name[0] == 0)
            break;

        /* get the attribute name */
        strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;

        /* determine the attribute type */
        switch (aptr->at_type) {
        case TCHAR:
                atype = "char";
                break;
        case TNUM:
                atype = "num";
                break;
        default:
                atype = "<error>";
                break;
        }

        /* output the attribute definition */
        if (strlen(aname) < 8)
            fprintf(fp,"\t%s\t\t%s\t%d\n",aname,atype,aptr->at_size);
        else
            fprintf(fp,"\t%s\t%s\t%d\n",aname,atype,aptr->at_size);
    }

    /* output the relation size */
    fprintf(fp,") %d\n",sptr->sc_relation->rl_tmax);

    /* close the relation */
    db_rclose(sptr);

    /* close the output file */
    if (fp != stdout)
        fclose(fp);

    /* return successfully */
    return (TRUE);
}

