home *** CD-ROM | disk | FTP | other *** search
- /*
- * METALBASE 5.1
- *
- * Released January 1st, 1993 by Huan-Ti [ t-richj@microsoft.com ]
- *
- */
-
- #include <mbase.h>
- #include "internal.h"
-
-
- /*
- * SERVICE ROUTINES -----------------------------------------------------------
- *
- */
-
- bool
- fSerialIdx (rel, idx)
- relation *rel;
- int idx;
- {
- int fld;
-
- if (rel == RNULL) Error (MB_BAD_REL);
-
- if (idx < 0 || idx >= rel->nIdx) Error (MB_BAD_IDX);
-
-
- for (fld = 0; fld < rel->nIdxFld[idx]; fld++)
- {
- if (rel->fldType[ rel->idxFld[idx][fld] ] == T_SERIAL)
- return TRUE;
- }
-
- lblERROR:
- return FALSE;
- }
-
- relation *
- mb_new ()
- {
- relation *rel;
-
- if ((rel = New (relation)) == RNULL)
- {
- Error (MB_NO_MEMORY);
- }
-
- rel->nIdx = 0;
- rel->nFld = 0;
- rel->serial = 0L;
-
- SetError (MB_OKAY);
-
- lblERROR:
- return rel;
- }
-
- mb_err
- mb_addindex (rel, name, fDups, desc)
- relation *rel;
- char *name, *desc;
- bool fDups;
- {
- charptr pch, line;
- char temp[128];
- int i, n;
-
-
- if (_identify (rel) != -1) Error (MB_BAD_REL);
-
- if (! name || ! *name) Error (MB_BAD_INDEX);
-
- if (! desc || *desc < '0' || *desc > '9') Error (MB_BAD_INDEX);
-
- if ((n = rel->nIdx) >= MAX_IDX) Error (MB_BAD_INDEX);
-
- if ( (fDups != TRUE) && (fDups != FALSE) ) Error (MB_BAD_INDEX);
-
-
- rel->fDups[n] = fDups;
-
- strcpy (rel->idxName[n], name);
-
- strcpy (temp, desc);
- line = temp;
-
- for (i = 0; i < MAX_COMP -1; i++)
- {
- if ((pch = strchr (line, ',')) == NULL)
- break;
- *pch = 0;
-
- rel->idxFld[n][i] = atoi (line);
-
- if (rel->idxFld[n][i] >= rel->nFld) Error (MB_BAD_FLD);
- if (rel->fldType[ rel->idxFld[n][i] ] == T_MCHAR) Error (MB_BAD_FLD);
- if (rel->fldType[ rel->idxFld[n][i] ] == T_MBYTE) Error (MB_BAD_FLD);
-
- line = pch+1;
- }
-
- rel->idxFld[n][i] = atoi (line);
- rel->nIdxFld[n] = i+1;
-
- if (rel->idxFld[n][i] >= rel->nFld) Error (MB_BAD_FLD);
- if (rel->fldType[ rel->idxFld[n][i] ] == T_MCHAR) Error (MB_BAD_FLD);
- if (rel->fldType[ rel->idxFld[n][i] ] == T_MBYTE) Error (MB_BAD_FLD);
-
- rel->nIdx++;
-
- if (fSerialIdx (rel, n))
- {
- rel->fDups[n] = FALSE;
- }
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
- mb_err
- mb_addfield (rel, name, type, arg)
- relation *rel;
- char *name;
- ftype type;
- long arg;
- {
- int i;
-
-
- if (rel->nFld >= MAX_FLD) Error (MB_BAD_FIELD);
-
- if (! name || ! *name) Error (MB_BAD_FIELD);
-
- if (type < T_CHAR) Error (MB_BAD_FIELD);
- if (type > T_LASTTYPE) Error (MB_BAD_FIELD);
-
-
- if (type == T_SERIAL)
- {
- rel->serial = arg; /* serial is temporary storage for NextSerial */
-
- for (i = 0; i < rel->nFld; i++)
- {
- if (rel->fldType[i] == T_SERIAL)
- Error (MB_DUP_SERIAL);
- }
- }
-
- if (type == T_CHAR || type == T_BYTE)
- {
- if (arg <= 0L)
- Error (MB_BAD_LEN);
- }
-
- strcpy (rel->fldName [rel->nFld], name);
-
- switch (rel->fldType [rel->nFld] = type)
- {
- case T_CHAR: rel->cbLen [rel->nFld] = (int)arg; break;
- case T_SHORT: rel->cbLen [rel->nFld] = 2; break;
- case T_USHORT: rel->cbLen [rel->nFld] = 2; break;
- case T_LONG: rel->cbLen [rel->nFld] = 4; break;
- case T_ULONG: rel->cbLen [rel->nFld] = 4; break;
- case T_FLOAT: rel->cbLen [rel->nFld] = 4; break;
- case T_DOUBLE: rel->cbLen [rel->nFld] = 8; break;
- case T_MONEY: rel->cbLen [rel->nFld] = 8; break;
- case T_TIME: rel->cbLen [rel->nFld] = 4; break;
- case T_DATE: rel->cbLen [rel->nFld] = 4; break;
- case T_SERIAL: rel->cbLen [rel->nFld] = 4; break;
- case T_PHONE: rel->cbLen [rel->nFld] = 20; break;
- case T_BYTE: rel->cbLen [rel->nFld] = (int)arg; break;
- case T_MCHAR: rel->cbLen [rel->nFld] = cbMULTI; break;
- case T_MBYTE: rel->cbLen [rel->nFld] = cbMULTI; break;
- }
-
- rel->nFld ++;
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
-
- /*
- * CREATE ROUTINE -------------------------------------------------------------
- *
- */
-
- mb_err
- mb_create (rel, name, fMem)
- relation *rel;
- char *name;
- bool fMem;
- {
- char temp[140], *pch;
- int fld, idx;
- file fh;
- short tshort;
- long tlong;
- char tchar;
-
- (void)fMem; /* Reference for compiler's sake; this is just for expansion */
-
-
- if (! rel || _identify (rel) != -1) Error (MB_BAD_REL);
-
- if (! rel->nIdx) Error (MB_NO_INDICES);
-
- if (! rel->nFld) Error (MB_NO_FIELDS);
-
-
- /*
- * See if we can create the file (if it already exists, delete it).
- *
- */
-
- strcpy (temp, name);
- if (! strcmp ( (pch = &temp[strlen(temp) -4]), ".rel" ))
- *pch = 0;
-
- if ((pch = strrchr (temp, DIRSEP)) != NULL)
- strcpy (rel->relname, 1+pch);
- else
- strcpy (rel->relname, temp);
-
-
- /*
- * Oh; while we're creating files, create the .DAT file (if we need one):
- *
- */
-
- strcat (temp, ".dat");
- if (access (temp, 0) != -1)
- unlink (temp);
-
- rel->fMulti = FALSE;
- for (fld = 0; fld < rel->nFld; fld++)
- {
- if ( (rel->fldType[fld] == T_MCHAR) || (rel->fldType[fld] == T_MBYTE) )
- {
- rel->fMulti = TRUE;
- if ((fh = creatx (temp)) <= 0)
- {
- Error (MB_NO_WRITE);
- }
- close (fh);
- modex (temp, 0666); /* Make the file -rw-rw-rw- */
-
- if ((fh = openx (temp, OPENMODE)) <= 0)
- {
- unlink (temp);
- Error (MB_NO_WRITE);
- }
-
- tchar = verCURRENT;
- writx (fh, &tchar, 1); /* .DAT-file signature */
- tlong = 5L; writx (fh, &tlong, 4); /* First free-chain link */
- tlong = 0L; writx (fh, &tlong, 4); /* FC: Next link (0==none) */
- tlong = 0L; writx (fh, &tlong, 4); /* FC: Size (0==end-of-chain) */
-
- close (fh);
- break;
- }
- }
-
-
- /*
- * Now check if there's a .LCK, and delete it...
- *
- */
-
- if (! GetTmpDir (temp))
- {
- Error (MB_TMPDIR);
- }
- strcat (temp, rel->relname);
- strcat (temp, ".lck");
- if (access (temp, 0) != -1)
- unlink (temp);
-
-
- /*
- * Now we'll create the .REL file.
- *
- */
-
- strcpy (temp, name);
- if (strcmp ( (pch = &temp[strlen(temp) -4]), ".rel" ))
- strcat (temp, ".rel");
-
- if (access (temp, 0) != -1)
- unlink (temp);
-
- if ((fh = creatx (temp)) <= 0)
- {
- Error (MB_NO_WRITE);
- }
- close (fh);
- modex (temp, 0666); /* Make the file -rw-rw-rw- */
-
- if ((fh = openx (temp, OPENMODE)) <= 0)
- {
- unlink (temp); /* We made it, but can't open it, so delete it. */
- Error (MB_NO_WRITE);
- }
-
- /*
- * Great; we've created the file. Now fill it out...
- *
- */
-
- temp[0] = verCURRENT; /* MetalBase Signature */
- temp[1] = (char)((rel->fMulti) ? 2 : 0); /* Work flag=1, fMulti=2 */
- writx (fh, temp, 2);
-
- tlong = 0L;
- writx (fh, &tlong, 4); /* Number of unindexed recs */
- writx (fh, &tlong, 4); /* Pointers to fields */
- writx (fh, &tlong, 4); /* Pointers to indices */
- writx (fh, &tlong, 4); /* Pointers to records */
- writx (fh, &tlong, 4); /* Number of records */
-
- writx (fh, &rel->serial, 4); /* Next serial value */
-
- tshort = (short)rel->nFld;
- writx (fh, &tshort, 2); /* Number of fields */
-
- tshort = (short)rel->nIdx;
- writx (fh, &tshort, 2); /* Number of indices */
-
- for (idx = 0; idx < rel->nIdx; idx++)
- writx (fh, &tlong, 4); /* Top of each index tree */
-
- /*
- * That was ugly. We're now ready to write the fields' descriptions...
- *
- */
-
- tlong = lseek (fh, 0L, 1); /* Remember where we are, and */
- lseek (fh, POS_FIELDPTR, 0); /* write the position as the */
- writx (fh, &tlong, 4); /* pointer to the fields' */
- lseek (fh, tlong, 0); /* descriptions; then go back */
-
- /*
- * A: var*F.....Fields' descriptions:
- * byte 0 : Type (0-10, as listed above)
- * bytes 1-2 : Size (short/ used only for char fields)
- * bytes 3-? : Name (max len = 20, terminated by '|')
- *
- */
-
- for (fld = 0; fld < rel->nFld; fld++)
- {
- temp[0] = (char)rel->fldType[fld]; writx (fh, temp, 1);
- tshort = (short)rel->cbLen[fld]; writx (fh, &tshort, 2);
-
- writx (fh, rel->fldName[fld], strlen (rel->fldName[fld]));
- writx (fh, "|", 1);
- }
-
- /*
- * That was uglier. We're now ready to write the indices' descriptions...
- *
- */
-
- tlong = lseek (fh, 0L, 1); /* Remember where we are, and */
- lseek (fh, POS_INDEXPTR, 0); /* write the position as the */
- writx (fh, &tlong, 4); /* pointer to the indices' */
- lseek (fh, tlong, 0); /* descriptions; then go back */
-
- /*
- * B: var*I.....Indices' descriptions:
- * byte 0 : Type (0-1, 0==nodups, 1==dups)
- * bytes 1 : Number of fields in this index
- * bytes 2-? : Name (max len = 20, terminated by ':')
- * --- : Each field's sequential # (as short, 0-based)
- * 1.......Separator ('\n')
- *
- */
-
- for (idx = 0; idx < rel->nIdx; idx++)
- {
- temp[0] = (char)(rel->fDups[idx]); /* TRUE if duplicates allowed */
- temp[1] = (char)(rel->nIdxFld[idx]); /* Number of fields in index */
-
- writx (fh, temp, 2);
-
- writx (fh, rel->idxName[idx], strlen (rel->idxName[idx]));
- writx (fh, ":", 1);
-
- for (fld = 0; fld < rel->nIdxFld [idx]; fld++)
- {
- tshort = (short)rel->idxFld [idx][fld];
- writx (fh, &tshort, 2);
- }
- }
-
- /*
- * There's a reserved segment, 128 bytes long, right here. I'll think of
- * something to put here, promise...
- *
- */
-
- rel->posRes = lseek (fh, 0L, 1); /* Remember current position */
-
- temp[0] = 0; /* 0==enc key not chosen yet */
- temp[1] = 0; /* unused if temp[0]==0 */
- writx (fh, temp, 2);
-
- for (fld = 0; fld < 126; fld++) /* And now, write a great big */
- temp[fld] = 0; /* lump of nothing here. */
- writx (fh, temp, 126);
-
- writx (fh, "\n", 1); /* Remember where we are, and */
- tlong = lseek (fh, 0L, 1); /* write this position as the */
- lseek (fh, POS_RECZERO, 0); /* pointer to the first */
- writx (fh, &tlong, 4); /* record. */
-
- rel->posRecZ = tlong;
-
- close (fh);
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
-