## root/dbeng/dblocal.c

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following definitions.

1. db_initialize
2. db_open
3. db_close
4. db_next
5. db_top
6. db_get_rec
7. db_get_rec_size
8. db_get_field_size
9. db_get_subfield_size
10. db_get_subsubfield_size
11. db_get_field
12. db_get_subfield
13. db_get_subsubfield
14. db_goto
15. db_count
16. db_put_field
17. db_put_subfield
18. db_put_subsubfield
19. db_write
20. db_delete
21. db_get_delete_flag
22. db_set_delete_flag
23. db_pack
24. db_find
25. db_find_field
26. db_find_part
27. db_find_field_part
28. db_get_nfields
29. db_get_nsubfields
30. db_get_nsubsubfields
31. db_get_rec_num
32. db_get_pos
33. db_set_pos
34. db_get_sort_max_mem
35. db_set_sort_max_mem
36. db_get_sort_max_open_bin
37. db_set_sort_max_open_bin
38. db_get_change_rec_flag
39. db_set_change_rec_flag
40. db_get_enf_change_rec_flag
41. db_set_enf_change_rec_flag
42. db_get_autopack
43. db_set_autopack
44. db_get_rec_count
45. db_new
46. db_get_is_table_locked
47. db_set_is_table_locked
48. db_new_table
49. db_get_open_table_list
50. db_delete_table
51. db_exist
52. db_clear_table
53. db_copy_table
54. db_sort
55. db_delete_field
56. db_delete_subfield
57. db_delete_subsubfield
58. db_get_catalog_list
59. db_end
60. db_atid_lookup

    /* A high level api module for the single user version of 'DBENG'
       (Bbuuzzb). Rick Smereka, Copyright (C) 1997-2004.

       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; either version 2 of the License, or
       (at your option) any later version.

       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 this program; if not, get a copy via the Internet at
       http://gnu.org/copyleft/gpl.html or write to the Free Software
       Foundation, Inc., 59 Temple Place, Suite 330, Boston,
       MA 02111-1307 USA

       You can contact the author via email at rsmereka@future-lab.com

       Original QNX (flat model) version. Jan/97, Rick Smereka

       Modified to use the system logger. May/97, Rick Smereka

       Re-wrote and changed the API. Oct/97, Rick Smereka

       Added functions to manage 'is_table_locked' flag. Dec/97,
       Rick Smereka

       Added function 'db_set_pos'. Nov/98, Rick Smereka

       Ported to 32bit Windows under CodeWarrior V4.
       Dec/98, Rick Smereka

       Ported to HP-UX under GNU C 2.8.1.
       Jan/99, Rick Smereka

       Added functions 'db_get_tmp_path' and 'db_get_error_log' and
       then moved and renamed these in 'dblocfg.c'.
       Feb/99, Rick Smereka

       Ported to Red Hat Linux 5.2, Jul/99, Rick Smereka

       Added include of 'flsocket.h'. Mar/2000, Rick Smereka

       Cleaned up debug messages. Apr/2000, Rick Smereka

       Added function 'db_get_open_table_list'. Jun/2001,
       Rick Smereka

       Fixed bug in 'db_next' where a call to 'sys_log' after
       record fetch when record was NULL would cause an
       exception. Nov/2001, Rick Smereka

       Added functions 'db_get_nsubfields', 'db_get_subfield_size'
       'db_get_subfield', 'db_put_subfield', 'db_get_nsubsubfields',
       'db_get_subsubfield_size', 'db_get_subsubfield' and
       'db_put_subsubfield'. Dec/2001, Rick Smereka

       Added support for automatic field, subfield and subsubfield
       append using the value zero. Functions 'db_put_field',
       'db_put_subfield' and 'db_put_subsubfield' now allow a zero
       value (in the field, subfield and subsubfield number parameter)
       to signify an append. Added function 'db_delete_table'. Added
       function 'db_exist'. May/2002, Rick Smereka

       Added function 'db_copy_table'. Jun/2002, Rick Smereka

       Added parameter to function 'db_get_open_table_list'.
       Added function 'db_sort'. Aug/2002, Rick Smereka

       Added functions 'db_get_sort_max_mem', 'db_set_sort_max_mem',
       'db_get_sort_max_open_bin' and 'db_set_sort_max_open_bin'.
       Ported to Debian Linux. Nov/2002, Rick Smereka

       Added functions 'db_delete_field', 'db_delete_subfield'
       and 'db_delete_subsubfield'. Mar/2003, Rick Smereka

       Added function 'db_end'. Jun/2003, Rick Smereka

       Added function 'db_get_catalog_list'. Nov/2003, Rick Smereka

       Added 'deleted_count' parameter in function 'db_count' and
       removed 'allopt' parameter. Added 'deleted_count' parameter
       to function 'db_get_rec_count'.  Removed save and restore
       of the 'process_deleted' flag in function 'db_count'.
       Jan/2004, Rick Smereka

       Added functions 'db_get_autopack' and 'db_set_autopack'.
       Changed all logging calls from 'sys_log' to 'logman'.
       Mar/2004, Rick Smereka */

    #include "stdhead.h"
    #include "dbmess.h"
    #include "dbeng.h"
    #include "dblocal.h"
    #include "dbengsrt.h"
    #include "dbiocode.h"
    #include "dbengcat.h"

    extern struct dbeng_table *dbeng_head;

    /* Note in each function that has the parameter 'tid' which
       is the table ID returned when the table is opened using 'db_open'. */

    int db_initialize(void)
    {
       /* Initialize the database engine. Should be called once
          per session. */

       char mname[25];
       int ret;

       strcpy(mname, "db_initialize");
       logman("%s:enter", mname);

       if ((ret = dbeng_initialize()) != DBENG_OK)
          {
          db_io_code_log(mname, "init error", ret);
          return(ret);
          }

       db_io_code_log(mname, "normal exit", DBENG_OK);
       return(DBENG_OK);
    }

    int db_open(char *filename, int *tid)
    {
       /* Open a table. The 'filename' is mandatory and consists of the
          full path and filename. File name must be no larger than
          1023 bytes each and must not contain spaces. Function returns
          'DBENG_OK' upon success, a error code otherwise. The table
          ID is returned in 'tid' upon success. */

       char mname[50];
       int ret;

       strcpy(mname, "db_open");
       logman("%s:enter", mname);

       if (filename == NULL || !strlen(filename))
          {
          db_io_code_log(mname, "no file name", DBENG_INVALID_FILE_NAME);
          return(DBENG_INVALID_FILE_NAME);
          }

       /* put a reasonable 1kb limit on the file name itself */

       if (strlen(filename) > 1023)
          {
          db_io_code_log(mname, "too long[filename]", DBENG_FILENAME_TOO_LONG);
          return(DBENG_FILENAME_TOO_LONG);
          }

       ret = dbeng_open_table(filename, tid);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_close(int tid)
    {
       /* Close a table. Table ID is expected in 'tid'.
          Function returns 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_close");
       logman("%s:enter", mname);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_close_table(ot);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_next(int tid)
    {
       /* Perform next record command. Function returns 'DBENG_OK' upon
          success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_next");
       logman("%s:enter", mname);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_get_recd(ot);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_top(int tid)
    {
       /* Goto the top of a table. Function returns 'DBENG_OK' upon
          success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_top");
       logman("%s:enter", mname);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_goto_top(ot);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_rec(int tid, char *rec_out)
    {
       /* Get complete table record. The file pointer is not advanced to
          the next record. The current record contents are returned.
          Record data is returned in 'rec_out' upon success.
          'rec_out' must be large enough to hold the record.
          Function returns 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_rec");
       logman("%s:enter", mname);

       if (rec_out == (char *)NULL)
          {
          db_io_code_log(mname, "null[rec_out]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       rec_out[0] = EOS;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_get_rec(ot, rec_out);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_rec_size(int tid, int *rec_size)
    {
       /* Get table record size or length. Record size is returned in
          'rec_size' upon success. Function returns 'DBENG_OK' upon
          success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_rec_size");
       logman("%s:enter", mname);

       if (rec_size == (int *)NULL)
          {
          db_io_code_log(mname, "null[rec_size]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *rec_size = 0;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_rec_size(ot, rec_size);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_field_size(int tid, int fnum, int *field_size)
    {
       /* Get size of a field in the current record. Variable 'field_size'
          will be loaded with the field size upon success.
          Function returns 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       char mes[75];
       int ret;

       strcpy(mname, "db_get_field_size");

       if (fnum <= 0)
          {
          db_io_code_log(mname, "out of range[fnum]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_size == (int *)NULL)
          {
          db_io_code_log(mname, "null[field_size]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *field_size = 0;
       logman("%s:enter,t=%d,f=%d", mname, tid, fnum);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_field_size(ot, fnum, field_size);
       db_io_code_string(ret, mes);
       logman("%s:exit,f=%d,s=%d,rc=%s", mname, fnum, *field_size, mes);
       return(ret);
    }

    int db_get_subfield_size(int tid, int fnum, int sfnum, int *subfield_size)
    {
       /* Get size of a sub-field in the field 'fnum'. Variable 'subfield_size'
          will be loaded with the sub-field size upon success.
          Function returns 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_get_subfield_size";
       char mes[75];
       int ret;

       if (fnum <= 0)
          {
          db_io_code_log(mname, "out of range[fnum]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (sfnum <= 0)
          {
          db_io_code_log(mname, "out of range[sfnum]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_size == (int *)NULL)
          {
          db_io_code_log(mname, "null[subfield_size]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *subfield_size = 0;
       logman("%s:enter,t=%d,f=%d,sf=%d", mname, tid, fnum, sfnum);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to locate '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_subfield_size(ot, fnum, sfnum, subfield_size);
       db_io_code_string(ret, mes);
       logman("%s:exit,s=%d,rc=%s", mname, *subfield_size, mes);
       return(ret);
    }

    int db_get_subsubfield_size(int tid, int fnum, int sfnum, int ssfnum,
                                int *subsubfield_size)
    {
       /* Get size of a sub-sub-field in the sub-field 'sfnum'. Variable
          'subsubfield_size' will be loaded with the sub-sub-field size
          upon success.  Function returns 'DBENG_OK' upon success, an
          error code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_get_subsubfield_size";
       char mes[75];
       int ret;

       if (fnum <= 0)
          {
          db_io_code_log(mname, "out of range[fnum]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (sfnum <= 0)
          {
          db_io_code_log(mname, "out of range[sfnum]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (ssfnum <= 0)
          {
          db_io_code_log(mname, "out of range[ssfnum]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subsubfield_size == (int *)NULL)
          {
          db_io_code_log(mname, "null[subsubfield_size]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *subsubfield_size = 0;
       logman("%s:enter,t=%d,f=%d,sf=%d,ssf=%d", mname, tid, fnum,
                     sfnum, ssfnum);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to locate '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_subsubfield_size(ot, fnum, sfnum, ssfnum, subsubfield_size);
       db_io_code_string(ret, mes);
       logman("%s:exit,s=%d,rc=%s", mname, *subsubfield_size, mes);
       return(ret);
    }

    int db_get_field(int tid, int field_num, char *field_out)
    {
       /* Get field data. Field contents are returned in 'field_out'
          upon success. Function returns 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_field");

       if (field_num <= 0)
          {
          db_io_code_log(mname, "illegal field number", DBENG_NO_SUCH_FIELD);
          return(DBENG_NO_SUCH_FIELD);
          }

       if (field_out == (char *)NULL)
          {
          db_io_code_log(mname, "null[field_out]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       field_out[0] = EOS;
       logman("%s:enter,t=%d,f=%d", mname, tid, field_num);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_get_field(ot, field_out, field_num);

       if (ret != DBENG_OK)
          {
          field_out[0] = EOS;
          db_io_code_log(mname, "returning null field", ret);
          return(ret);
          }

       logman("%s:normal exit,fo=%s,l=%d", mname, field_out,
                     strlen(field_out));
       return(DBENG_OK);
    }

    int db_get_subfield(int tid, int field_num, int subfield_num,
                        char *subfield_out)
    {
       /* Get sub-field data. Sub-field contents are returned in 'subfield_out'
          upon success. Function returns 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_get_subfield";
       int ret;

       if (field_num <= 0)
          {
          db_io_code_log(mname, "out of range[field_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num <= 0)
          {
          db_io_code_log(mname, "out of range[subfield_num]",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_out == (char *)NULL)
          {
          db_io_code_log(mname, "null[subfield_out]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       subfield_out[0] = EOS;
       logman("%s:enter,t=%d,f=%d,sf=%d", mname, tid, field_num,
                     subfield_num);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to locate '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_get_subfield(ot, subfield_out, field_num, subfield_num);

       if (ret != DBENG_OK)
          {
          subfield_out[0] = EOS;
          db_io_code_log(mname, "returning null sub-field", ret);
          return(ret);
          }

       logman("%s:normal exit,sfo=%s,l=%d", mname, subfield_out,
                     strlen(subfield_out));
       return(DBENG_OK);
    }

    int db_get_subsubfield(int tid, int field_num, int subfield_num,
                           int subsubfield_num, char *subsubfield_out)
    {
       /* Get sub-sub-field data. Sub-sub-field contents are returned in
          'subsubfield_out' upon success. Function returns 'DBENG_OK'
          upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_get_subsubfield";
       int ret;

       if (field_num <= 0)
          {
          db_io_code_log(mname, "out of range[field_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num <= 0)
          {
          db_io_code_log(mname, "out of range[subfield_num]",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subsubfield_num <= 0)
          {
          db_io_code_log(mname, "out of range[subsubfield_num]",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subsubfield_out == (char *)NULL)
          {
          db_io_code_log(mname, "null[subsubfield_out]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       subsubfield_out[0] = EOS;
       logman("%s:enter,t=%d,f=%d,sf=%d,ssf=%d", mname, tid, field_num,
                     subfield_num, subsubfield_num);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to locate '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_get_subsubfield(ot, subsubfield_out, field_num, subfield_num,
                                   subsubfield_num);

       if (ret != DBENG_OK)
          {
          subsubfield_out[0] = EOS;
          db_io_code_log(mname, "returning null sub-sub-field", ret);
          return(ret);
          }

       logman("%s:normal exit,ssfo=%s,l=%d", mname, subsubfield_out,
                     strlen(subsubfield_out));
       return(DBENG_OK);
    }

    int db_goto(int tid, long rec_num)
    {
       /* Goto a specific record number. Function returns 'DBENG_OK'
          upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[10];
       int ret;

       strcpy(mname, "db_goto");
       logman("%s:enter", mname);

       if (rec_num <= 0L)
          {
           db_io_code_log(mname, "illegal record number",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_goto_record(ot, rec_num);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_count(int tid, long *active_num, long *deleted_num)
    {
       /* Count the number of records in a table. Function returns
          'DBENG_OK' with the record count loaded upon success,
          an error code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_count";
       int ret;

       logman("%s:enter", mname);

       if (active_num == (long *)NULL)
          {
          db_io_code_log(mname, "null[active_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (deleted_num == (long *)NULL)
          {
          db_io_code_log(mname, "null[deleted_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *active_num = *deleted_num = 0L;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_count_rec(ot, active_num, deleted_num);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_put_field(int tid, int field_num, char *field_data)
    {
       /* Place a string into a field in the current record. Function returns
          'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_put_field";
       int stat;

       if (field_num < 0)
          {
          db_io_code_log(mname, "illegal field number",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_data == NULL)
          {
          db_io_code_log(mname, "null[field_data]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       logman("%s:enter,t=%d,f=%d,d=%s,l=%d", mname, tid, field_num,
               field_data, strlen(field_data));

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       stat = dbeng_put_field(ot, field_data, field_num);
       db_io_code_log(mname, "normal exit", stat);
       return(stat);
    }

    int db_put_subfield(int tid, int field_num, int subfield_num, char *sf_data)
    {
       /* Place a string into a sub-field in the current record. Function returns
          'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_put_subfield";
       int stat;

       if (field_num < 0)
          {
          db_io_code_log(mname, "out of range[field_num]",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num < 0)
          {
          db_io_code_log(mname, "out of range[subfield_num]",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (sf_data == (char *)NULL)
          {
          db_io_code_log(mname, "null[sf_data]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       logman("%s:enter,t=%d,f=%d,sf=%d,d=%s,l=%d", mname, tid, field_num,
                     subfield_num, sf_data, strlen(sf_data));

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to locate '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       stat = dbeng_put_subfield(ot, sf_data, field_num, subfield_num);
       db_io_code_log(mname, "normal exit", stat);
       return(stat);
    }

    int db_put_subsubfield(int tid, int field_num, int subfield_num,
                           int subsubfield_num, char *ssf_data)
    {
       /* Place a string into a sub-sub-field in the current record. Function
          returns 'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_put_subsubfield";
       int stat;

       if (field_num < 0)
          {
          db_io_code_log(mname, "out of range[field_num]",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num < 0)
          {
          db_io_code_log(mname, "out of range[subfield_num]",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subsubfield_num < 0)
          {
          db_io_code_log(mname, "out of range[subsubfield_num]",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (ssf_data == (char *)NULL)
          {
          db_io_code_log(mname, "null[ssf_data]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       logman("%s:enter,t=%d,f=%d,sf=%d,ssf=%d,d=%s,l=%d", mname, tid,
                     field_num, subfield_num, subsubfield_num, ssf_data,
                     strlen(ssf_data));

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to locate '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       stat = dbeng_put_subsubfield(ot, ssf_data, field_num, subfield_num,
                                    subsubfield_num);
       db_io_code_log(mname, "normal exit", stat);
       return(stat);
    }

    int db_write(int tid)
    {
       /* Write a record to the table. If the record already exists, it
          will be re-written, otherwise a new record will be written.
          Field data must have already been placed into the record.
          Function returns 'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[10];
       int ret;

       strcpy(mname, "db_write");
       logman("%s:enter", mname);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_write_recd(ot);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_delete(int tid)
    {
       /* Delete the current record from a table. Only the current record
          will be deleted. Function returns 'DBENG_OK' upon success, an
          error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_delete");
       logman("%s:enter", mname);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_delete_recd(ot);   /* plus re-position to top of table */
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_delete_flag(int tid, int *value)
    {
       /* Get the 'delete_flag' for a table. Function returns 'DBENG_OK'
          upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_delete_flag");
       logman("%s:enter", mname);

       if (value == (int *)NULL)
          {
          db_io_code_log(mname, "null[value]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *value = FALSE;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_delete_flag(ot, value);
       db_io_code_log(mname, "normal exit", ret);
       return(DBENG_OK);
    }

    int db_set_delete_flag(int tid, int value)
    {
       /* Set the 'delete_flag' for a table. 'value' must be one of 'TRUE'
          or 'FALSE'. Function returns 'DBENG_OK' upon success, an error
          code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_set_delete_flag");
       logman("%s:enter", mname);

       if (value != TRUE && value != FALSE)
          {
          db_io_code_log(mname, "'not 0|1[value]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_set_delete_flag(ot, value);
       db_io_code_log(mname, "normal exit", ret);
       return(DBENG_OK);
    }

    int db_pack(int tid)
    {
       /* Pack a table. Function returns 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_pack");
       logman("%s:enter", mname);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_pack_table(ot);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_find(int tid, int cs_flag, char *fdata, int *field_num)
    {
       /* Find data in a table field. Only whole field will match.
          All fields in each record will be searched. Comparison
          is based on 'cs_flag' for case sensitivity. Field number that
          matched will be loaded into 'field_num' upon a successful find.
          Function will return 'DBENG_OK' if a record was found, an error
          code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_find");
       logman("%s:enter", mname);

       if (cs_flag != TRUE && cs_flag != FALSE)
          {
          db_io_code_log(mname, "not 0|1[cs_flag]",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (fdata == NULL)
          {
          db_io_code_log(mname, "null[fdata]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num == NULL)
          {
          db_io_code_log(mname, "null[field_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *field_num = 0;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_find(ot, cs_flag, fdata, field_num);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_find_field(int tid, int cs_flag, char *fdata, int field_num)
    {
       /* Find data in a table field. Only whole field will match.
          Only field 'field_num' will be searched. String comparison
          is based on 'cs_flag' for case sensitivity. Function will return
          'DBENG_OK' if a record was found, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_find_field");
       logman("%s:enter", mname);

       if (cs_flag != TRUE && cs_flag != FALSE)
          {
          db_io_code_log(mname, "not 0|1[cs_flag]",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (fdata == NULL)
          {
          db_io_code_log(mname, "null[fdata]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          db_io_code_log(mname, "illegal[field_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_find_field(ot, cs_flag, fdata, field_num);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_find_part(int tid, int cs_flag, char *fdata, int *field_num)
    {
       /* Find data in a table field. Any part of the field will match.
          All fields in each record will be searched. Comparison
          is based on 'cs_flag' for case sensitivity. Field number that
          matched will be loaded into 'field_num' upon a successful find.
          Function will return 'DBENG_OK' if a record was found, an error
          code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_find_part");
       logman("%s:enter", mname);

       if (cs_flag != TRUE && cs_flag != FALSE)
          {
          db_io_code_log(mname, "not 0|1[cs_flag]",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (fdata == NULL)
          {
          db_io_code_log(mname, "null[fdata]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num == NULL)
          {
          db_io_code_log(mname, "null[field_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *field_num = 0;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_find_part(ot, cs_flag, fdata, field_num);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_find_field_part(int tid, int cs_flag, char *fdata, int field_num)
    {
       /* Find data in a table field. Any part of the field will match.
          Only field 'field_num' will be searched. String comparison
          is based on 'cs_flag' for case sensitivity. Function will return
          'DBENG_OK' if a record was found, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_find_field_part");
       logman("%s:enter", mname);

       if (cs_flag != TRUE && cs_flag != FALSE)
          {
          db_io_code_log(mname, "not 0|1[cs_flag]",
                            DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (fdata == NULL)
          {
          db_io_code_log(mname, "null[fdata]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          db_io_code_log(mname, "illegal[field_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_find_field_part(ot, cs_flag, fdata, field_num);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_nfields(int tid, int *nfields)
    {
       /* Get number of fields in the current record. Number of fields is
          returned in 'nfields' upon success. Function returns 'DBENG_OK'
          upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_nfields");
       logman("%s:enter", mname);

       if (nfields == (int *)NULL)
          {
          db_io_code_log(mname, "null[nfields]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_nfields(ot, nfields);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_nsubfields(int tid, int field_num, int *nsubfields)
    {
       /* Get number of sub-fields in the 'field_num' field. Number of sub-fields
          is returned in 'nsubfields' upon success. Function returns 'DBENG_OK'
          upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_get_nsubfields";
       int ret;

       logman("%s:enter", mname);

       if (nsubfields == (int *)NULL)
          {
          db_io_code_log(mname, "null[nsubfields]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          db_io_code_log(mname, "out of range[field_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to locate '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_nsubfields(ot, field_num, nsubfields);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_nsubsubfields(int tid, int field_num, int subfield_num,
                             int *nsubsubfields)
    {
       /* Get number of sub-sub-fields in the 'subfield_num' sub-field. Number
          of sub-sub-fields is returned in 'nsubsubfields' upon success. Function
          returns 'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_get_nsubsubfields";
       int ret;

       logman("%s:enter", mname);

       if (nsubsubfields == (int *)NULL)
          {
          db_io_code_log(mname, "null[nsubsubfields]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (field_num <= 0)
          {
          db_io_code_log(mname, "out of range[field_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (subfield_num <= 0)
          {
          db_io_code_log(mname, "out of range[subfield_num]",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to locate '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_nsubsubfields(ot, field_num, subfield_num, nsubsubfields);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_rec_num(int tid, long *rec_num)
    {
       /* Get the current record number. The record number is returned in
          'rec_num' along with 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_rec_num");
       logman("%s:enter", mname);

       if (rec_num == (long *)NULL)
          {
          db_io_code_log(mname, "null[rec_num]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *rec_num = 0L;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_rec_num(ot, rec_num);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_pos(int tid, long *pos)
    {
       /* Get the current record starting file position. The position is
          returned in 'pos' along with 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_pos");
       logman("%s:enter", mname);

       if (pos == (long *)NULL)
          {
          db_io_code_log(mname, "null[pos]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *pos = 0L;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_pos(ot, pos);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_set_pos(int tid, long pos)
    {
       /* Set the table file position. BE VERY CAREFUL.
          Make sure there is a record at the specified
          file position. This function, if misused,
          can cause the engine to shutdown. Function
          returns 'DBENG_OK' upon success, an error
          code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_set_pos");
       logman("%s:enter", mname);

       if (pos < 0L)
          {
          db_io_code_log(mname, "illegal[pos]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_set_pos(ot, pos);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_sort_max_mem(int tid, long *mem)
    {
       /* Get the current allowable sort max memory allocation. The value is
          returned in 'mem' along with 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_get_sort_max_mem";
       int ret;

       logman("%s:enter", mname);

       if (mem == (long *)NULL)
          {
          db_io_code_log(mname, "null[mem]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *mem = 0L;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_sort_get_max_mem(ot, mem);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_set_sort_max_mem(int tid, long mem)
    {
       /* Set the allowable maximum sort memory.
          Function returns a 'dbeng' code. */

       struct dbeng_table *ot;
       char mname[] = "db_set_sort_max_mem";
       int ret;

       logman("%s:enter", mname);

       if (mem <= 0L)
          {
          db_io_code_log(mname, "illegal[mem]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_sort_set_max_mem(ot, mem);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_sort_max_open_bin(int tid, int *open_bin)
    {
       /* Get the current allowable sort number of open bin tables. The value is
          returned in 'open_bin' along with 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_get_sort_max_open_bin";
       int ret;

       logman("%s:enter", mname);

       if (open_bin == (int *)NULL)
          {
          db_io_code_log(mname, "null[open_bin]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *open_bin = 0;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_sort_get_max_open_bin(ot, open_bin);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_set_sort_max_open_bin(int tid, int open_bin)
    {
       /* Set the allowable maximum number of open bin tables during sort.
          Function returns a 'dbeng' code. */

       struct dbeng_table *ot;
       char mname[] = "db_set_sort_max_open_bin";
       int ret;

       logman("%s:enter", mname);

       if (open_bin <= 0)
          {
          db_io_code_log(mname, "illegal[open_bin]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_sort_set_max_open_bin(ot, open_bin);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_change_rec_flag(int tid, int *flag)
    {
       /* Get the current value of 'change_rec_flag'. The flag value is
          returned in 'flag' along with 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_change_rec_flag");
       logman("%s:enter", mname);

       if (flag == (int *)NULL)
          {
          db_io_code_log(mname, "null[flag]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *flag = FALSE;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_change_rec_flag(ot, flag);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_set_change_rec_flag(int tid, int flag)
    {
       /* Set the value of 'change_rec_flag'. The function returns
          'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_set_change_rec_flag");
       logman("%s:enter", mname);

       if (flag != TRUE && flag != FALSE)
          {
          db_io_code_log(mname, "invalid[flag]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_set_change_rec_flag(ot, flag);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_enf_change_rec_flag(int tid, int *flag)
    {
       /* Get the current value of 'enforce_change_rec_flag'. The flag value is
          returned in 'flag' along with 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_enf_change_rec_flag");
       logman("%s:enter", mname);

       if (flag == (int *)NULL)
          {
          db_io_code_log(mname, "null[flag]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *flag = FALSE;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_enf_change_rec_flag(ot, flag);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_set_enf_change_rec_flag(int tid, int flag)
    {
       /* Set the value of 'enforce_change_rec_flag'. The function returns
          'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_set_enf_change_rec_flag");
       logman("%s:enter", mname);

       if (flag != TRUE && flag != FALSE)
          {
          db_io_code_log(mname, "invalid[flag]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_set_enf_change_rec_flag(ot, flag);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_autopack(int tid, int *pvalue)
    {
       /* Get the current value of 'autopack'. The value is
          returned in 'pvalue' along with 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_get_autopack";
       int ret;

       logman("%s:enter", mname);

       if (pvalue == (int *)NULL)
          {
          db_io_code_log(mname, "null[pvalue]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *pvalue = 0;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_autopack(ot, pvalue);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_set_autopack(int tid, int pvalue)
    {
       /* Set the value of 'autopack'. The function returns
          'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_set_autopack";
       int ret;

       logman("%s:enter", mname);

       if (pvalue < 0)
          {
          db_io_code_log(mname, "invalid[pvalue]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_set_autopack(ot, pvalue);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_rec_count(int tid, long *active_count, long *deleted_count)
    {
       /* Get the current active and deleted record count. The count value is
          returned in along with 'DBENG_OK' upon success, an error code
          otherwise. Note that this function does not actually count the records
          in the table but reports on what the database manager thinks is the
          record count. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_get_record_count");
       logman("%s:enter", mname);

       if (active_count == (long *)NULL)
          {
          db_io_code_log(mname, "null[active_count]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (deleted_count == (long *)NULL)
          {
          db_io_code_log(mname, "null[deleted_count]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *active_count = *deleted_count = 0L;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_rec_count(ot, active_count, deleted_count);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_new(int tid)
    {
       /* Prepare for a new record. Function will return 'DBENG_OK' upon
          success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[50];
       int ret;

       strcpy(mname, "db_new");
       logman("%s:enter", mname);

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_new(ot);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_is_table_locked(int tid, int *flag)
    {
       /* Get the current value of 'is_table_locked'. The flag value is
          returned in 'flag' along with 'DBENG_OK' upon success, an error code
          otherwise. */

       struct dbeng_table *ot;
       char mname[25];
       int ret;

       strcpy(mname, "db_get_is_table_locked");
       logman("%s:enter", mname);

       if (flag == (int *)NULL)
          {
          db_io_code_log(mname, "null[flag]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       *flag = FALSE;

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_is_table_locked(ot, flag);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_set_is_table_locked(int tid, int flag)
    {
       /* Set the value of 'is_table_locked'. The function returns
          'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *ot;
       char mname[25];
       int ret;

       strcpy(mname, "db_set_is_table_locked");
       logman("%s:enter", mname);

       if (flag != TRUE && flag != FALSE)
          {
          db_io_code_log(mname, "invalid[flag]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_set_is_table_locked(ot, flag);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_new_table(char *filename, int *tid)
    {
       /* Create a new table. If 'tid' is a positive
          number, also open the table. Function
          returns 'DBENG_OK' upon success with
          the table 'tid' loaded if open was
          requested. Function returns an engine
          i/o code otherwise. */

       char mname[50];
       int ret;

       strcpy(mname, "db_new_table");
       logman("%s:enter", mname);

       if (filename == NULL || !strlen(filename))
          {
          db_io_code_log(mname, "no file name", DBENG_INVALID_FILE_NAME);
          return(DBENG_INVALID_FILE_NAME);
          }

       /* put a reasonable limit on the file name itself */

       if (strlen(filename) >= DBENG_PATH_LIMIT)
          {
          db_io_code_log(mname, "too long[filename]", DBENG_FILENAME_TOO_LONG);
          return(DBENG_FILENAME_TOO_LONG);
          }

       ret = dbeng_new_table(filename, tid);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_open_table_list(char *pat, char *list_out)
    {
       /* Get and return a list of all open tables.
          List is returned in 'list_out' upon
          success. 'list_out' must already be allocated
          to sufficient size. The parameter 'pat' may
          contain an acceptable pattern to the function
          'pmatch' of physical file names. Function
          returns a 'dbeng' code. */

       char mname[] = "db_get_open_table_list";
       int ret;

       logman("%s:enter", mname);

       if (list_out == NULL)
          {
          db_io_code_log(mname, "null[list_out]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       ret = dbeng_open_table_list(pat, list_out);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_delete_table(char *tname)
    {
       /* Delete a table by its table name (physical file name in single
          user version, logical table name in multiuser with the catalog
          flag high). Table must not be open by any tid. Function
          returns a 'dbeng' code. */

       char mname[] = "db_delete_table";
       int ret;

       logman("%s:enter", mname);

       if (tname == (char *)NULL || !strlen(tname))
          {
          db_io_code_log(mname, "null or empty[tname]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       ret = dbeng_delete_table(tname);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_exist(char *tname, int *exist_flag)
    {
       /* Determine whether a table exists. Function returns a 'dbeng'
          code. */

       char mname[] = "db_exist";
       int ret;

       logman("%s:enter", mname);

       if (tname == (char *)NULL || !strlen(tname))
          {
          db_io_code_log(mname, "null or empty[tname]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (exist_flag == (int *)NULL)
          {
          db_io_code_log(mname, "null[exist_flag", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       ret = dbeng_exist(tname, exist_flag);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_clear_table(char *tname)
    {
       /* Delete a table by its table name (physical file name in single
          user version). Table must not be open by any tid. Function
          returns a 'dbeng' code. */

       char mname[] = "db_clear_table";
       int ret;

       logman("%s:enter", mname);

       if (tname == (char *)NULL || !strlen(tname))
          {
          db_io_code_log(mname, "null or empty[tname]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       ret = dbeng_clear_table(tname);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_copy_table(int src_tid, int dest_tid)
    {
       /* Copy a table from source to destination. The function returns
          'DBENG_OK' upon success, an error code otherwise. */

       struct dbeng_table *src_ot, *dest_ot;
       char mname[] = "db_copy_table";
       int ret;

       logman("%s:enter", mname);

       if (src_tid <= 0)
          {
          db_io_code_log(mname, "tid out of range[src_tid]",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (dest_tid <= 0)
          {
          db_io_code_log(mname, "tid out of range[dest_tid]",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((src_ot = db_atid_lookup(src_tid)) == DBENG_OT_NULL)
          {
          db_io_code_log(mname, "bad ret from db_atid_lookup[src_tid]",
                         DBENG_NO_SUCH_TID);
          return(DBENG_NO_SUCH_TID);
          }

       if ((dest_ot = db_atid_lookup(dest_tid)) == DBENG_OT_NULL)
          {
          db_io_code_log(mname, "bad ret from db_atid_lookup[dest_tid]",
                         DBENG_NO_SUCH_TID);
          return(DBENG_NO_SUCH_TID);
          }

       if ((ret = dbeng_copy_table(src_ot, dest_ot)) != DBENG_OK)
          {
          db_io_code_log(mname, "bad ret from dbeng_copy_table", ret);
          return(ret);
          }

       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_sort(int tid, char *specs)
    {
       /* Sort a table. Sort specs are expected in 'specs'.
          Function returns 'DBENG_OK' upon success, an error
          code otherwise. */

       struct dbeng_table *ot;
       char mname[] = "db_sort";
       int ret;

       logman("%s:enter", mname);

       if (tid <= 0)
          {
          db_io_code_log(mname, "tid out of range", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == DBENG_OT_NULL)
          {
          db_io_code_log(mname, "bad ret from db_atid_lookup[tid]",
                         DBENG_NO_SUCH_TID);
          return(DBENG_NO_SUCH_TID);
          }

       if ((ret = dbeng_sort(ot, specs)) != DBENG_OK)
          {
          db_io_code_log(mname, "bad ret from dbeng_sort", ret);
          return(ret);
          }

       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_delete_field(int tid, int fnum)
    {
       /* Completly remove a specific field within the record.
          Function returns a 'dbeng' code. */

       struct dbeng_table *ot;
       char mname[] = "db_delete_field";
       int ret;

       logman("%s:enter", mname);

       if (fnum <= 0)
          {
          db_io_code_log(mname, "illegal field number",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_delete_field(ot, fnum);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_delete_subfield(int tid, int fnum, int sfnum)
    {
       /* Completly remove a specific subfield within the record.
          Function returns a 'dbeng' code. */

       struct dbeng_table *ot;
       char mname[] = "db_delete_subfield";
       int ret;

       logman("%s:enter", mname);

       if (fnum <= 0)
          {
          db_io_code_log(mname, "illegal field number",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (sfnum <= 0)
          {
          db_io_code_log(mname, "illegal subfield number",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_delete_subfield(ot, fnum, sfnum);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_delete_subsubfield(int tid, int fnum, int sfnum, int ssfnum)
    {
       /* Completly remove a specific subsubfield within the record.
          Function returns a 'dbeng' code. */

       struct dbeng_table *ot;
       char mname[] = "db_delete_subsubfield";
       int ret;

       logman("%s:enter", mname);

       if (fnum <= 0)
          {
          db_io_code_log(mname, "illegal field number",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (sfnum <= 0)
          {
          db_io_code_log(mname, "illegal subfield number",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if (ssfnum <= 0)
          {
          db_io_code_log(mname, "illegal subsubfield number",
                         DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       if ((ot = db_atid_lookup(tid)) == (struct dbeng_table *)NULL)
          {
          logman("%s:unable to open '%d',no such table", mname, tid);
          return(DBENG_NO_SUCH_TID);
          }

       ret = dbeng_delete_subsubfield(ot, fnum, sfnum, ssfnum);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    int db_get_catalog_list(char *pat, char *list_out)
    {
       /* Get and return a list of catalog entries.
          List is returned in 'list_out' upon
          success. 'list_out' must already be allocated
          to sufficient size. The parameter 'pat' may
          contain an acceptable pattern to the function
          'pmatch' of logical table names. Function
          returns a 'dbeng' code. */

       char mname[] = "db_get_catalog_list";
       int ret;

       logman("%s:enter", mname);

       if (list_out == NULL)
          {
          db_io_code_log(mname, "null[list_out]", DBENG_INVALID_FUNCTION);
          return(DBENG_INVALID_FUNCTION);
          }

       ret = dbeng_catalog_list(pat, list_out);
       db_io_code_log(mname, "normal exit", ret);
       return(ret);
    }

    void db_end(void)
    {
       // Prepare for termination. Close everything.

       dbeng_terminate();
    }

    struct dbeng_table *db_atid_lookup(int tid)
    {
       /* Take a table ID ('tid') and perform a lookup.
          Function returns a pointer to the found table
          upon success, a 'NULL' pointer otherwise. */

       struct dbeng_table *ot;
       int done = FALSE;
       int found = FALSE;

       if (dbeng_head == DBENG_OT_NULL)
          return((struct dbeng_table *)NULL);

       if (tid <= 0)
          return((struct dbeng_table *)NULL);

       ot = dbeng_head;

       while(!done)
          {
          if (ot == DBENG_OT_NULL)
             done = TRUE;
          else
             {
             if (ot->tid == tid)
                {
                done = TRUE;
                found = TRUE;
                }
             }

          if (!done && !found)
             ot = ot->next;
          }

       if (!found)
          ot = (struct dbeng_table *)NULL;

       return(ot);
    }

/* [<][>][^][v][top][bottom][index][help] */