home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / database / cdbms / database.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-01  |  12.1 KB  |  636 lines

  1. /* ----------------- database.c ---------------------- */
  2.  
  3. #include <stdio.h>
  4. #include "cdata.h"
  5. #include "keys.h"
  6.  
  7. void build_b();            /* Builds a new B-tree                */
  8. RPTR locate();            /* Searches a B-tree for a key      */
  9. RPTR nextkey();            /* Gets address of the next key     */
  10. RPTR prevkey();            /* Gets address of the previous key */
  11. RPTR firstkey();          /* Gets address of first key        */
  12. RPTR lastkey();           /* Gets address of last key         */
  13. RPTR currkey();            /* Gets address of current key          */
  14. void file_close();      /* Closes a data file               */
  15. RPTR new_record();      /* Adds a record to a file          */
  16. char *malloc();
  17. void init_index(), cls_index(), del_indexes();
  18.  
  19. int db_opened = FALSE;    /* data base opened indicator       */
  20. int curr_fd [MXFILS];    /* current file descriptor            */
  21. RPTR curr_a [MXFILS];    /* current record file address        */
  22. char *bfs [MXFILS];        /* file i/o buffers */
  23. int bfd [MXFILS] [MXINDEX];
  24. char dbpath [64];
  25. int notice_posted = 0;
  26. int prev_col = 0, prev_row = 0;
  27.  
  28. /* ------------------ open the data base ----------------- */
  29. void db_open(path, fl)
  30. char *path;
  31. int *fl;
  32. {
  33.     char fnm [64];
  34.     int i;
  35.  
  36.     if (!db_opened)    {
  37.         for (i = 0; i < MXFILS; i++)
  38.             curr_fd [i] = -1;
  39.         db_opened = TRUE;
  40.     }
  41.     strcpy(dbpath, path);
  42.     while (*fl != -1)    {
  43.         sprintf(fnm, "%s%.8s.dat", path, dbfiles [*fl]);
  44.         curr_fd [*fl] = file_open(fnm);
  45.         init_index(path, *fl);
  46.         if ((bfs [*fl] = malloc(rlen(*fl))) == NULL)    {
  47.             errno = D_OM;
  48.             dberror();
  49.         }
  50.         fl++;
  51.     }
  52. }
  53.  
  54. /* ------------- add a record to a file --------------- */
  55. int add_rcd(f, bf)
  56. int f;
  57. char *bf;
  58. {
  59.     RPTR ad;
  60.     extern RPTR new_record();
  61.     int rtn;
  62.  
  63.     if ((rtn = relate_rcd(f, bf)) != ERROR)    {
  64.         ad = new_record(curr_fd [f], bf);
  65.         if ((rtn = add_indexes(f, bf, ad)) == ERROR)    {
  66.             errno = D_DUPL;
  67.             delete_record(curr_fd [f], ad);
  68.         }
  69.     }
  70.     return rtn;
  71. }
  72.  
  73. /* ------------- find a record in a file -------------- */
  74. int find_rcd(f,k,key,bf)
  75. int f;            /* file number            */
  76. int k;            /* key number            */
  77. char *key;        /* key value            */
  78. char *bf;        /* buffer for record    */
  79. {
  80.     RPTR ad;
  81.     
  82.     if ((ad = locate(treeno(f,k), key)) == 0)    {
  83.         errno = D_NF;
  84.         return ERROR;
  85.     }
  86.     return getrcd(f, ad, bf);
  87. }
  88.  
  89. /* -------- verify that a record is in a file --------- */
  90. int verify_rcd(f,k,key)
  91. int f;            /* file number            */
  92. int k;            /* key number            */
  93. char *key;        /* key value            */
  94. {
  95.     if (locate(treeno(f,k), key) == (RPTR) 0)    {
  96.         errno = D_NF;
  97.         return ERROR;
  98.     }
  99.     return OK;
  100. }
  101.  
  102. /* ------- find the first indexed record in a file -------- */
  103. int first_rcd(f,k,bf)
  104. int f;            /* file number            */
  105. int k;            /* key number            */
  106. char *bf;        /* buffer for record    */
  107. {
  108.     RPTR ad;
  109.     
  110.     if ((ad = firstkey(treeno(f,k))) == 0)    {
  111.         errno = D_EOF;
  112.         return ERROR;
  113.     }
  114.     return getrcd(f, ad, bf);
  115. }
  116.  
  117. /* ------- find the last indexed record in a file -------- */
  118. int last_rcd(f,k,bf)
  119. int f;            /* file number            */
  120. int k;            /* key number            */
  121. char *bf;        /* buffer for record    */
  122. {
  123.     RPTR ad;
  124.     
  125.     if ((ad = lastkey(treeno(f,k))) == 0)    {
  126.         errno = D_BOF;
  127.         return ERROR;
  128.     }
  129.     return getrcd(f, ad, bf);
  130. }
  131.  
  132. /* ------------- find the next record in a file ----------- */
  133. int next_rcd(f,k,bf)
  134. int f;            /* file number            */
  135. int k;            /* key number            */
  136. char *bf;        /* buffer for record    */
  137. {
  138.     RPTR ad;
  139.     
  140.     if ((ad = nextkey(treeno(f, k))) == 0)    {
  141.         errno = D_EOF;
  142.         return ERROR;
  143.     }
  144.     return getrcd(f, ad, bf);
  145. }
  146.  
  147. /* -------- find the previous record in a file --------- */
  148. int prev_rcd(f,k,bf)
  149. int f;            /* file number            */
  150. int k;            /* key number            */
  151. char *bf;        /* buffer for record    */
  152. {
  153.     RPTR ad;
  154.     
  155.     if ((ad = prevkey(treeno(f,k))) == 0)    {
  156.         errno = D_BOF;
  157.         return ERROR;
  158.     }
  159.     return getrcd(f, ad, bf);
  160. }
  161.  
  162. /* ----- return the current record to the data base ------- */
  163. int rtn_rcd(f, bf)
  164. int f;
  165. char *bf;
  166. {
  167.     int rtn;
  168.  
  169.     if (curr_a [f] == 0)    {
  170.         errno = D_PRIOR;
  171.         return ERROR;
  172.     }
  173.     if ((rtn = relate_rcd(f, bf)) != ERROR)    {
  174.         del_indexes(f, curr_a [f]);
  175.         if ((rtn = add_indexes(f, bf, curr_a [f])) == OK)
  176.             put_record(curr_fd [f], curr_a [f], bf);
  177.         else
  178.             errno = D_DUPL;
  179.     }
  180.     return rtn;
  181. }
  182.  
  183. /* ------- delete the current record from the file -------- */
  184. int del_rcd(f)
  185. int f;
  186. {
  187.     if (curr_a [f])    {
  188.         del_indexes(f, curr_a [f]); 
  189.         delete_record(curr_fd [f], curr_a [f]);
  190.         curr_a [f] = 0;
  191.         return OK;
  192.     }
  193.     errno = D_PRIOR;
  194.     return ERROR;
  195. }
  196.  
  197.  
  198.  
  199.  
  200.  
  201. /* ---------- find the current record in a file ----------- */
  202. int curr_rcd(f,k,bf)
  203. int f;            /* file number            */
  204. int k;            /* key number            */
  205. char *bf;        /* buffer for record    */
  206. {
  207.     RPTR ad;
  208.     extern RPTR currkey();
  209.  
  210.     if ((ad = currkey(treeno(f,k))) == 0)    {
  211.         errno = D_NF;
  212.         return ERROR;
  213.     }
  214.     getrcd(f, ad, bf);
  215.     return OK;
  216. }
  217.  
  218. /* --------- get the next physical
  219.                 sequential record from the file ------- */
  220. int seqrcd(f, bf)
  221. int f;
  222. RPTR *bf;
  223. {
  224.     RPTR ad;
  225.     int rtn;
  226.  
  227.     do    {
  228.         ad = ++curr_a [f];
  229.         if ((rtn = (rel_rcd(f,ad,bf)))==ERROR && errno!=D_NF)
  230.             break;
  231.     }    while (errno == D_NF);
  232.     return rtn;
  233. }
  234.  
  235. /* ----------------- close the data base ------------------ */
  236. void db_cls()
  237. {
  238.     int f;
  239.  
  240.     for (f = 0; f < MXFILS; f++)
  241.         if (curr_fd [f] != -1)    {
  242.             file_close(curr_fd [f]);
  243.             cls_index(f);
  244.             free(bfs[f]);
  245.             curr_fd [f] = -1;
  246.         }
  247.     db_opened = FALSE;
  248. }
  249.  
  250. /* -------------------- data base error routine ----------- */
  251. void dberror()
  252. {
  253.     static char *ers [] = {
  254.         "Record not found",
  255.         "No prior record",
  256.         "End of file",
  257.         "Beginning of file",
  258.         "Record already exists",
  259.         "Not enough memory",
  260.         "Index corrupted",
  261.         "Disk i/o error"
  262.     };
  263.     static int fat [] = {0,1,0,0,0,1,1,1};
  264.  
  265.     error_message(ers [errno-1]);
  266.     if (fat [errno-1])
  267.         exit(1);
  268. }
  269.  
  270. /* ----------- compute file record length ----------------- */
  271. int rlen(f)
  272. int f;
  273. {
  274.     return epos(0, file_ele [f]);
  275. }
  276.  
  277.  
  278.  
  279.  
  280.  
  281. /* ---------- initialize a file record buffer ------------ */
  282. void init_rcd(f, bf)
  283. int f;            /* file number */
  284. char *bf;        /* buffer */
  285. {
  286.     clrrcd(bf, file_ele[f]);
  287. }
  288.  
  289. /* -------- set a generic record buffer to blanks --------- */
  290. void clrrcd(bf, els)
  291. char *bf;        /* buffer */
  292. int *els;        /* data element list */
  293. {
  294.     int ln, i = 0, el;
  295.     char *rb;
  296.  
  297.     while (*(els + i))    {
  298.         el = *(els + i);
  299.         rb = bf + epos(el, els);
  300.         ln = ellen [el - 1];
  301.         while (ln--)
  302.             *rb++ = ' ';
  303.         *rb = '\0';
  304.         i++;
  305.     }
  306. }
  307.  
  308.  
  309. /* ------- move data from one record to another ------- */
  310. void rcd_fill(s, d, slist, dlist)
  311. char *s;        /* source record buffer */
  312. char *d;        /* destination record buffer */
  313. int *slist;        /* source data element list */
  314. int *dlist;        /* destination data element list */
  315. {
  316.     int *s1, *d1;
  317.  
  318.     s1 = slist;
  319.     while (*s1)    {
  320.         d1 = dlist;
  321.         while (*d1)    {
  322.             if (*s1 == *d1)
  323.                 strcpy(d+epos(*d1,dlist), s+epos(*s1,slist));
  324.             d1++;
  325.         }
  326.         s1++;
  327.     }
  328. }
  329.  
  330. /* -------- compute relative position of
  331.                 a data element within a record -----*/
  332. int epos(el, list)
  333. int el;            /* element number */
  334. int *list;        /* record element list */
  335. {
  336.     int len = 0;
  337.  
  338.     while (el != *list)
  339.         len += ellen [(*list++)-1] + 1;
  340.     return len;
  341. }
  342.  
  343. /* ------------- index management functions ------------ */
  344. /* ---- initialize the indices for a file ---- */
  345. static void init_index(path, f)
  346. char *path;        /* where the data base is */
  347. int f;            /* file number */
  348. {
  349.     char xname [64];
  350.     int x = 0;
  351.  
  352.     while (*(index_ele [f] + x))    {
  353.         sprintf(xname, "%s%.8s.x%02d",path,dbfiles[f],x+1);
  354.         if ((bfd [f] [x++] = btree_init(xname)) == ERROR)    {
  355.             printf("\n%s", xname);
  356.             errno = D_INDXC;
  357.             dberror();
  358.         }
  359.     }
  360. }
  361.  
  362. /* ---- build the indices for a file ---- */
  363. void build_index(path, f)
  364. char *path;
  365. int f;            /* file number */
  366. {
  367.     char xname [64];
  368.     int x = 0, x1;
  369.     int len;
  370.  
  371.     while (*(index_ele [f] + x))    {
  372.         sprintf(xname, "%s%.8s.x%02d", path, dbfiles[f], x+1);
  373.         len = 0;
  374.         x1 = 0;
  375.         while (*(*(index_ele [f] + x) + x1))
  376.             len += ellen [*(*(index_ele [f] + x) + (x1++))-1];
  377.         build_b(xname, len);
  378.         x++;
  379.     }
  380. }
  381.  
  382. /* ----- close the indices for a file ------ */
  383. static void cls_index(f)
  384. int f;
  385. {
  386.     int x = 0;
  387.  
  388.     while (*(index_ele [f] + x))    {
  389.         if (bfd [f] [x] != ERROR)
  390.             btree_close(bfd [f] [x]);
  391.         x++;
  392.     }
  393. }
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401. /* ---- add index values from a record to the indices ---- */
  402. int add_indexes(f, bf, ad)
  403. int f;
  404. char *bf;
  405. RPTR ad;
  406. {
  407.     int x = 0;
  408.     int i;
  409.     char key [MXKEYLEN];
  410.  
  411.     while (*(index_ele [f] + x))    {
  412.         *key = '\0';
  413.         i = 0;
  414.         while(*(*(index_ele [f] + x) + i))
  415.             strcat(key,
  416.                 bf +
  417.             epos(*(*(index_ele[f]+x)+(i++)),file_ele [f]));
  418.         if (insertkey(bfd [f] [x], key, ad, !x) == ERROR)
  419.               return ERROR;
  420.         x++;
  421.     }
  422.       return OK;
  423. }
  424.  
  425. /* --- delete index values in a record from the indices --- */
  426. static void del_indexes(f, ad)
  427. int f;
  428. RPTR ad;
  429. {
  430.     char *bf;
  431.     int x = 0;
  432.     int i;
  433.     char key [MXKEYLEN];
  434.  
  435.     if ((bf = malloc(rlen(f))) == NULL)    {
  436.         errno = D_OM;
  437.         dberror();
  438.     }
  439.     get_record(curr_fd [f], ad, bf);
  440.     while (*(index_ele [f] + x))    {
  441.         *key = '\0';
  442.         i = 0;
  443.         while (*(*(index_ele [f] + x) + i))
  444.             strcat(key,
  445.                 bf +
  446.             epos(*(*(index_ele[f]+x)+(i++)), file_ele [f]));
  447.         deletekey(bfd [f] [x++], key, ad);
  448.     }
  449.     free(bf);
  450. }
  451.  
  452.  
  453. /* ---- compute tree number from file and key number ---- */
  454. static int treeno(f, k)
  455. int f, k;
  456. {
  457.     return bfd [f] [k - 1];
  458. }
  459.  
  460.  
  461. /* ---- validate the contents of a record where its file is
  462.         related to another file in the data base ---------- */
  463. static int relate_rcd(f, bf)
  464. int f;
  465. char *bf;
  466. {
  467.     int fx = 0, mx, *fp;
  468.     static int ff[] = {0, -1};
  469.     char *cp;
  470.  
  471.     while (dbfiles [fx])    {
  472.         if (fx != f && *(*(index_ele [fx]) + 1) == 0)    {
  473.             mx = *(*(index_ele [fx]));
  474.             fp = file_ele [f];
  475.             while (*fp)    {
  476.                 if (*fp == mx)    {
  477.                     cp = bf + epos(mx, file_ele [f]);
  478.                     if (data_in(cp))    {
  479.                         if (curr_fd[fx] == -1)    {
  480.                             *ff = fx;
  481.                             db_open(dbpath, ff);
  482.                         }
  483.                         if (verify_rcd(fx, 1, cp) == ERROR)
  484.                             return ERROR;
  485.                     }
  486.                     break;
  487.                 }
  488.                 fp++;
  489.             }
  490.         }
  491.         fx++;
  492.     }
  493.     return OK;
  494. }
  495.  
  496. /* ----- test a string for data. return TRUE if any ---- */
  497. static int data_in(c)
  498. char *c;
  499. {
  500.     while (*c == ' ')        
  501.         c++;
  502.     return (*c != '\0');
  503. }
  504.  
  505. /* ------------- get a record from a file -------------- */
  506. static int getrcd(f, ad, bf)
  507. int f;
  508. RPTR ad;
  509. char *bf;
  510. {
  511.     get_record(curr_fd [f], ad, bf);
  512.     curr_a [f] = ad;
  513.     return OK;
  514. }
  515.  
  516. extern FHEADER fh [];
  517.  
  518.  
  519.  
  520.  
  521. /* ----- find a record by relative record number ------ */
  522. static int rel_rcd(f, ad, bf)
  523. int f;            /* file number            */
  524. RPTR ad;
  525. int *bf;
  526. {
  527.     errno = 0;
  528.     if (ad >= fh [curr_fd [f]].next_record)    {
  529.         errno = D_EOF;
  530.         return ERROR;
  531.     }
  532.     getrcd(f, ad, bf);
  533.     if (*bf == -1)    {
  534.         errno = D_NF;
  535.         return ERROR;
  536.     }
  537.     return OK;
  538. }
  539.  
  540. /* -------------- error message -------- */
  541. void error_message(s)
  542. char *s;
  543. {
  544.     put_char(BELL);
  545.     post_notice(s);
  546. }
  547.  
  548. /* --------- clear notice line ------------- */
  549. void clear_notice()
  550. {
  551.     int i;
  552.  
  553.     if (notice_posted)    {
  554.         cursor(0,24);
  555.         for (i = 0; i < 50; i++)
  556.             put_char(' ');
  557.         notice_posted = FALSE;
  558.         cursor(prev_col, prev_row);
  559.     }
  560. }
  561.  
  562. /* ----------- post a notice ----------------- */
  563. void post_notice(s)
  564. char *s;
  565. {
  566.     clear_notice();
  567.     cursor(0,24);
  568.     while (*s)    {
  569.         put_char(isprint(*s) ? *s : '.');
  570.         s++;
  571.     }
  572.     cursor(prev_col, prev_row);
  573.     notice_posted = TRUE;
  574. }
  575.  
  576. /* ---------- Move a block -------- */
  577. void mov_mem(s, d, l)
  578. char *s, *d;
  579. int l;
  580. {
  581.     if (d > s)
  582.         while (l--)
  583.             *(d + l) = *(s + l);
  584.     else
  585.         while (l--)
  586.             *d++ = *s++;
  587. }
  588.  
  589.  
  590. /* --------- Set a block to a character value ----- */
  591. void set_mem(s, l, n)
  592. char *s, n;
  593. int l;
  594. {
  595.     while (l--)
  596.         *s++ = n;
  597. }
  598.  
  599.  
  600.  
  601.  
  602. /*
  603.  * Convert a file name into its file token.
  604.  * Return the token,
  605.  * or ERROR if the file name is not in the schema.
  606.  */
  607. int filename(fn)
  608. char *fn;
  609. {
  610.     char fname[32];
  611.     int f;
  612.     void name_cvt();
  613.  
  614.     name_cvt(fname, fn);
  615.     for (f = 0; dbfiles [f]; f++)
  616.         if (strcmp(fname, dbfiles [f]) == 0)
  617.             break;
  618.     if (dbfiles [f] == 0)    {
  619.         fprintf(stderr, "\nNo such file as %s", fname);
  620.         return ERROR;
  621.     }
  622.     return f;
  623. }
  624.  
  625. /* ----------- convert a name to upper case ---------- */
  626. void name_cvt(c2, c1)
  627. char *c1, *c2;
  628. {
  629.     while (*c1)    {
  630.         *c2 = toupper(*c1);
  631.         c1++;
  632.         c2++;
  633.     }
  634.     *c2 = '\0';
  635. }
  636.