home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / CONTRIB / MBASE / MBASE51.TAR / mbase51 / src / mb_creat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-04  |  11.0 KB  |  433 lines

  1. /*
  2.  * METALBASE 5.1
  3.  *
  4.  * Released January 1st, 1993 by Huan-Ti [ t-richj@microsoft.com ]
  5.  *
  6.  */
  7.  
  8. #include <mbase.h>
  9. #include "internal.h"
  10.  
  11.  
  12. /*
  13.  * SERVICE ROUTINES -----------------------------------------------------------
  14.  *
  15.  */
  16.  
  17. bool
  18. fSerialIdx (rel, idx)
  19. relation   *rel;
  20. int              idx;
  21. {
  22.    int  fld;
  23.  
  24.    if (rel == RNULL)                  Error (MB_BAD_REL);
  25.  
  26.    if (idx < 0 || idx >= rel->nIdx)   Error (MB_BAD_IDX);
  27.  
  28.  
  29.    for (fld = 0; fld < rel->nIdxFld[idx]; fld++)
  30.       {
  31.       if (rel->fldType[ rel->idxFld[idx][fld] ] == T_SERIAL)
  32.          return TRUE;
  33.       }
  34.  
  35. lblERROR:
  36.    return FALSE;
  37. }
  38.  
  39. relation *
  40. mb_new ()
  41. {
  42.    relation *rel;
  43.  
  44.    if ((rel = New (relation)) == RNULL)
  45.       {
  46.       Error (MB_NO_MEMORY);
  47.       }
  48.  
  49.    rel->nIdx = 0;
  50.    rel->nFld = 0;
  51.    rel->serial = 0L;
  52.  
  53.    SetError (MB_OKAY);
  54.  
  55. lblERROR:
  56.    return rel;
  57. }
  58.  
  59. mb_err
  60. mb_addindex (rel, name, fDups, desc)
  61. relation    *rel;
  62. char             *name,       *desc;
  63. bool                    fDups;
  64. {
  65.    charptr pch, line;
  66.    char    temp[128];
  67.    int     i,   n;
  68.  
  69.  
  70.    if (_identify (rel) != -1)                  Error (MB_BAD_REL);
  71.  
  72.    if (! name || ! *name)                      Error (MB_BAD_INDEX);
  73.  
  74.    if (! desc || *desc < '0' || *desc > '9')   Error (MB_BAD_INDEX);
  75.  
  76.    if ((n = rel->nIdx) >= MAX_IDX)             Error (MB_BAD_INDEX);
  77.  
  78.    if ( (fDups != TRUE) && (fDups != FALSE) )  Error (MB_BAD_INDEX);
  79.  
  80.  
  81.    rel->fDups[n] = fDups;
  82.  
  83.    strcpy (rel->idxName[n], name);
  84.  
  85.    strcpy (temp, desc);
  86.    line = temp;
  87.  
  88.    for (i = 0; i < MAX_COMP -1; i++)
  89.       {
  90.       if ((pch = strchr (line, ',')) == NULL)
  91.          break;
  92.       *pch = 0;
  93.  
  94.       rel->idxFld[n][i] = atoi (line);
  95.  
  96.       if (rel->idxFld[n][i] >= rel->nFld)                Error (MB_BAD_FLD);
  97.       if (rel->fldType[ rel->idxFld[n][i] ] == T_MCHAR)  Error (MB_BAD_FLD);
  98.       if (rel->fldType[ rel->idxFld[n][i] ] == T_MBYTE)  Error (MB_BAD_FLD);
  99.  
  100.       line = pch+1;
  101.       }
  102.  
  103.    rel->idxFld[n][i] = atoi (line);
  104.    rel->nIdxFld[n]   = i+1;
  105.  
  106.    if (rel->idxFld[n][i] >= rel->nFld)                Error (MB_BAD_FLD);
  107.    if (rel->fldType[ rel->idxFld[n][i] ] == T_MCHAR)  Error (MB_BAD_FLD);
  108.    if (rel->fldType[ rel->idxFld[n][i] ] == T_MBYTE)  Error (MB_BAD_FLD);
  109.  
  110.    rel->nIdx++;
  111.  
  112.    if (fSerialIdx (rel, n))
  113.       {
  114.       rel->fDups[n] = FALSE;
  115.       }
  116.  
  117.    SetError (MB_OKAY);
  118.  
  119. lblERROR:
  120.    return mb_errno;
  121. }
  122.  
  123. mb_err
  124. mb_addfield (rel, name, type, arg)
  125. relation    *rel;
  126. char             *name;
  127. ftype                   type;
  128. long                          arg;
  129. {
  130.    int  i;
  131.  
  132.  
  133.    if (rel->nFld >= MAX_FLD)  Error (MB_BAD_FIELD);
  134.  
  135.    if (! name || ! *name)     Error (MB_BAD_FIELD);
  136.  
  137.    if (type < T_CHAR)         Error (MB_BAD_FIELD);
  138.    if (type > T_LASTTYPE)     Error (MB_BAD_FIELD);
  139.  
  140.  
  141.    if (type == T_SERIAL)
  142.       {
  143.       rel->serial = arg;  /* serial is temporary storage for NextSerial */
  144.  
  145.       for (i = 0; i < rel->nFld; i++)
  146.          {
  147.          if (rel->fldType[i] == T_SERIAL)
  148.             Error (MB_DUP_SERIAL);
  149.          }
  150.       }
  151.  
  152.    if (type == T_CHAR || type == T_BYTE)
  153.       {
  154.       if (arg <= 0L)
  155.          Error (MB_BAD_LEN);
  156.       }
  157.  
  158.    strcpy (rel->fldName [rel->nFld], name);
  159.  
  160.    switch (rel->fldType [rel->nFld] = type)
  161.       {
  162.       case T_CHAR:    rel->cbLen [rel->nFld] = (int)arg;  break;
  163.       case T_SHORT:   rel->cbLen [rel->nFld] =  2;        break;
  164.       case T_USHORT:  rel->cbLen [rel->nFld] =  2;        break;
  165.       case T_LONG:    rel->cbLen [rel->nFld] =  4;        break;
  166.       case T_ULONG:   rel->cbLen [rel->nFld] =  4;        break;
  167.       case T_FLOAT:   rel->cbLen [rel->nFld] =  4;        break;
  168.       case T_DOUBLE:  rel->cbLen [rel->nFld] =  8;        break;
  169.       case T_MONEY:   rel->cbLen [rel->nFld] =  8;        break;
  170.       case T_TIME:    rel->cbLen [rel->nFld] =  4;        break;
  171.       case T_DATE:    rel->cbLen [rel->nFld] =  4;        break;
  172.       case T_SERIAL:  rel->cbLen [rel->nFld] =  4;        break;
  173.       case T_PHONE:   rel->cbLen [rel->nFld] = 20;        break;
  174.       case T_BYTE:    rel->cbLen [rel->nFld] = (int)arg;  break;
  175.       case T_MCHAR:   rel->cbLen [rel->nFld] = cbMULTI;   break;
  176.       case T_MBYTE:   rel->cbLen [rel->nFld] = cbMULTI;   break;
  177.       }
  178.  
  179.    rel->nFld ++;
  180.  
  181.    SetError (MB_OKAY);
  182.  
  183. lblERROR:
  184.    return mb_errno;
  185. }
  186.  
  187.  
  188. /*
  189.  * CREATE ROUTINE -------------------------------------------------------------
  190.  *
  191.  */
  192.  
  193. mb_err
  194. mb_create (rel, name, fMem)
  195. relation  *rel;
  196. char           *name;
  197. bool                  fMem;
  198. {
  199.    char   temp[140], *pch;
  200.    int    fld, idx;
  201.    file   fh;
  202.    short  tshort;
  203.    long   tlong;
  204.    char   tchar;
  205.  
  206.    (void)fMem;  /* Reference for compiler's sake; this is just for expansion */
  207.  
  208.  
  209.    if (! rel || _identify (rel) != -1)  Error (MB_BAD_REL);
  210.  
  211.    if (! rel->nIdx)                     Error (MB_NO_INDICES);
  212.  
  213.    if (! rel->nFld)                     Error (MB_NO_FIELDS);
  214.  
  215.  
  216. /*
  217.  * See if we can create the file (if it already exists, delete it).
  218.  *
  219.  */
  220.  
  221.    strcpy (temp, name);
  222.    if (! strcmp ( (pch = &temp[strlen(temp) -4]), ".rel" ))
  223.       *pch = 0;
  224.  
  225.    if ((pch = strrchr (temp, DIRSEP)) != NULL)
  226.       strcpy (rel->relname, 1+pch);
  227.    else
  228.       strcpy (rel->relname, temp);
  229.  
  230.  
  231. /*
  232.  * Oh; while we're creating files, create the .DAT file (if we need one):
  233.  *
  234.  */
  235.  
  236.    strcat (temp, ".dat");
  237.    if (access (temp, 0) != -1)
  238.       unlink (temp);
  239.  
  240.    rel->fMulti = FALSE;
  241.    for (fld = 0; fld < rel->nFld; fld++)
  242.       {
  243.       if ( (rel->fldType[fld] == T_MCHAR) || (rel->fldType[fld] == T_MBYTE) )
  244.          {
  245.          rel->fMulti = TRUE;
  246.          if ((fh = creatx (temp)) <= 0)
  247.             {
  248.             Error (MB_NO_WRITE);
  249.             }
  250.          close (fh);
  251.          modex (temp, 0666);   /* Make the file   -rw-rw-rw-  */
  252.  
  253.          if ((fh = openx (temp, OPENMODE)) <= 0)
  254.             {
  255.             unlink (temp);
  256.             Error (MB_NO_WRITE);
  257.             }
  258.  
  259.          tchar = verCURRENT;
  260.          writx (fh, &tchar, 1);                /* .DAT-file signature        */
  261.          tlong = 5L;  writx (fh, &tlong, 4);   /* First free-chain link      */
  262.          tlong = 0L;  writx (fh, &tlong, 4);   /* FC: Next link (0==none)    */
  263.          tlong = 0L;  writx (fh, &tlong, 4);   /* FC: Size (0==end-of-chain) */
  264.  
  265.          close (fh);
  266.          break;
  267.          }
  268.       }
  269.  
  270.  
  271. /*
  272.  * Now check if there's a .LCK, and delete it...
  273.  *
  274.  */
  275.  
  276.    if (! GetTmpDir (temp))
  277.       {
  278.       Error (MB_TMPDIR);
  279.       }
  280.    strcat (temp, rel->relname);
  281.    strcat (temp, ".lck");
  282.    if (access (temp, 0) != -1)
  283.       unlink (temp);
  284.  
  285.  
  286. /*
  287.  * Now we'll create the .REL file.
  288.  *
  289.  */
  290.  
  291.    strcpy (temp, name);
  292.    if (strcmp ( (pch = &temp[strlen(temp) -4]), ".rel" ))
  293.       strcat (temp, ".rel");
  294.  
  295.    if (access (temp, 0) != -1)
  296.       unlink (temp);
  297.  
  298.    if ((fh = creatx (temp)) <= 0)
  299.       {
  300.       Error (MB_NO_WRITE);
  301.       }
  302.    close (fh);
  303.    modex (temp, 0666);   /* Make the file   -rw-rw-rw-  */
  304.  
  305.    if ((fh = openx (temp, OPENMODE)) <= 0)
  306.       {
  307.       unlink (temp);         /* We made it, but can't open it, so delete it. */
  308.       Error (MB_NO_WRITE);
  309.       }
  310.  
  311. /*
  312.  * Great; we've created the file.  Now fill it out...
  313.  *
  314.  */
  315.  
  316.    temp[0] = verCURRENT;                       /* MetalBase Signature        */
  317.    temp[1] = (char)((rel->fMulti) ? 2 : 0);    /* Work flag=1, fMulti=2      */
  318.    writx (fh, temp, 2);
  319.  
  320.    tlong = 0L;
  321.    writx (fh, &tlong, 4);                      /* Number of unindexed recs   */
  322.    writx (fh, &tlong, 4);                      /* Pointers to fields         */
  323.    writx (fh, &tlong, 4);                      /* Pointers to indices        */
  324.    writx (fh, &tlong, 4);                      /* Pointers to records        */
  325.    writx (fh, &tlong, 4);                      /* Number of records          */
  326.  
  327.    writx (fh, &rel->serial, 4);                /* Next serial value          */
  328.  
  329.    tshort = (short)rel->nFld;
  330.    writx (fh, &tshort, 2);                     /* Number of fields           */
  331.  
  332.    tshort = (short)rel->nIdx;
  333.    writx (fh, &tshort, 2);                     /* Number of indices          */
  334.  
  335.    for (idx = 0; idx < rel->nIdx; idx++)
  336.       writx (fh, &tlong, 4);                   /* Top of each index tree     */
  337.  
  338. /*
  339.  * That was ugly.  We're now ready to write the fields' descriptions...
  340.  *
  341.  */
  342.  
  343.    tlong = lseek (fh, 0L, 1);                  /* Remember where we are, and */
  344.    lseek (fh, POS_FIELDPTR, 0);                /* write the position as the  */
  345.    writx (fh, &tlong, 4);                      /* pointer to the fields'     */
  346.    lseek (fh, tlong, 0);                       /* descriptions; then go back */
  347.  
  348. /*
  349.  * A: var*F.....Fields' descriptions:
  350.  *                 byte    0 : Type (0-10, as listed above)
  351.  *                 bytes 1-2 : Size (short/ used only for char fields)
  352.  *                 bytes 3-? : Name (max len = 20, terminated by '|')
  353.  *
  354.  */
  355.  
  356.    for (fld = 0; fld < rel->nFld; fld++)
  357.       {
  358.       temp[0] = (char)rel->fldType[fld];  writx (fh,  temp,   1);
  359.       tshort  = (short)rel->cbLen[fld];   writx (fh, &tshort, 2);
  360.  
  361.       writx (fh, rel->fldName[fld], strlen (rel->fldName[fld]));
  362.       writx (fh, "|", 1);
  363.       }
  364.  
  365. /*
  366.  * That was uglier.  We're now ready to write the indices' descriptions...
  367.  *
  368.  */
  369.  
  370.    tlong = lseek (fh, 0L, 1);                   /* Remember where we are, and */
  371.    lseek (fh, POS_INDEXPTR, 0);                 /* write the position as the  */
  372.    writx (fh, &tlong, 4);                       /* pointer to the indices'    */
  373.    lseek (fh, tlong, 0);                        /* descriptions; then go back */
  374.  
  375. /*
  376.  * B: var*I.....Indices' descriptions:
  377.  *                 byte    0 : Type (0-1, 0==nodups, 1==dups)
  378.  *                 bytes   1 : Number of fields in this index
  379.  *                 bytes 2-? : Name (max len = 20, terminated by ':')
  380.  *                       --- : Each field's sequential # (as short, 0-based)
  381.  *      1.......Separator ('\n')
  382.  *
  383.  */
  384.  
  385.    for (idx = 0; idx < rel->nIdx; idx++)
  386.       {
  387.       temp[0] = (char)(rel->fDups[idx]);       /* TRUE if duplicates allowed */
  388.       temp[1] = (char)(rel->nIdxFld[idx]);     /* Number of fields in index  */
  389.  
  390.       writx (fh, temp, 2);
  391.  
  392.       writx (fh, rel->idxName[idx], strlen (rel->idxName[idx]));
  393.       writx (fh, ":", 1);
  394.  
  395.       for (fld = 0; fld < rel->nIdxFld [idx]; fld++)
  396.          {
  397.          tshort = (short)rel->idxFld [idx][fld];
  398.          writx (fh, &tshort, 2);
  399.          }
  400.       }
  401.  
  402. /*
  403.  * There's a reserved segment, 128 bytes long, right here.  I'll think of
  404.  * something to put here, promise...
  405.  *
  406.  */
  407.  
  408.    rel->posRes = lseek (fh, 0L, 1);            /* Remember current position  */
  409.  
  410.    temp[0] = 0;                                /* 0==enc key not chosen yet  */
  411.    temp[1] = 0;                                /* unused if temp[0]==0       */
  412.    writx (fh, temp, 2);
  413.  
  414.    for (fld = 0; fld < 126; fld++)             /* And now, write a great big */
  415.       temp[fld] = 0;                           /* lump of nothing here.      */
  416.    writx (fh, temp, 126);
  417.  
  418.    writx (fh, "\n", 1);                        /* Remember where we are, and */
  419.    tlong = lseek (fh, 0L, 1);                  /* write this position as the */
  420.    lseek (fh, POS_RECZERO, 0);                 /* pointer to the first       */
  421.    writx (fh, &tlong, 4);                      /* record.                    */
  422.  
  423.    rel->posRecZ = tlong;
  424.  
  425.    close (fh);
  426.  
  427.    SetError (MB_OKAY);
  428.  
  429. lblERROR:
  430.    return mb_errno;
  431. }
  432.  
  433.