home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / lib / libpq / fe-dumpdata.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  9.4 KB  |  366 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    fe-dumpdata.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    Dump the returned tuples into a frontend buffer
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *    dump_type     - Dump the attributes
  10.  *    dump_tuple     - Dump a tuple
  11.  *    finish_dump     - End of a command (data stream)
  12.  *    dump_data     - Read and process the data stream from backend
  13.  *
  14.  *   NOTES
  15.  *
  16.  *   IDENTIFICATION
  17.  *    $Header: /private/postgres/src/lib/libpq/RCS/fe-dumpdata.c,v 1.11 1992/07/15 05:11:02 mao Exp $
  18.  * ----------------------------------------------------------------
  19.  */
  20.  
  21. #include "tmp/c.h"
  22.  
  23. #include "tmp/simplelists.h"
  24. #include "tmp/libpq-fe.h"
  25. #include "utils/exc.h"
  26.  
  27. RcsId("$Header: /private/postgres/src/lib/libpq/RCS/fe-dumpdata.c,v 1.11 1992/07/15 05:11:02 mao Exp $");
  28.  
  29. /* Define constants. */
  30.  
  31. #define BYTELEN 8
  32. #define MAXBYTES 128    /* MAXFIELDS / BYTELEN */
  33. #define MAXFIELDS 512
  34.  
  35. /* --------------------------------
  36.  *    dump_type - Dump the attributes
  37.  * --------------------------------
  38.  */
  39. void
  40. dump_type(types, nfields)
  41.     TypeBlock *types;
  42.     int nfields;
  43. {
  44.     int i;
  45.     TypeBlock *type;
  46.  
  47.     type = types;
  48.  
  49.     for (i = 0; i < nfields; i++) {
  50.     pq_getstr(type->name, NameLength);
  51.     type->adtid = pq_getint(4);
  52.     type->adtsize = pq_getint(2);
  53.     type++;
  54.     }
  55. }
  56.  
  57. /* --------------------------------
  58.  *    dump_tuple - Dump a tuple
  59.  * --------------------------------
  60.  */
  61. void
  62. dump_tuple(values,lengths, nfields)
  63.     char **values;
  64.      int *lengths;
  65.     int nfields;
  66. {
  67.     char     bitmap[MAXFIELDS];
  68.     int     bitmap_index = 0;
  69.     int     i;
  70.     unsigned     nbytes;        /* the number of bytes in bitmap */
  71.     char     bmap;        /* One byte of the bitmap */
  72.     int     bitcnt = 0;     /* number of bits examined in current byte */
  73.     int     vlen;        /* length of the current field value */
  74.     
  75.     nbytes = nfields / BYTELEN;
  76.     if ((nfields % BYTELEN) > 0) 
  77.     nbytes++;
  78.  
  79.     pq_getnchar(bitmap, 0, nbytes);
  80.     bmap = bitmap[bitmap_index];
  81.     
  82.     /* Read in all the attribute values. */
  83.     for (i = 0; i < nfields; i++) {
  84.     /* If the field value is absent, do nothing. */
  85.     if (!(bmap & 0200))
  86.         values[i] = NULL;
  87.     else {
  88.         /* Get the value length (the first four bytes are for length). */
  89.         vlen = pq_getint(4) - 4;
  90.         /* Allocate storage for the value. */
  91.         values[i] = pbuf_addValues(vlen + 1);
  92.         /* Read in the value. */
  93.         pq_getnchar(values[i], 0, vlen);
  94.         lengths[i] = vlen;
  95.         /* Put an end of string there to make life easier. */
  96.         values[i][vlen] = '\0';
  97.         pqdebug("%s", values[i]);
  98.     }
  99.  
  100.     /* Get the approriate bitmap. */
  101.     bitcnt++;
  102.     if (bitcnt == BYTELEN) {
  103.         bitmap_index++;
  104.         bmap = bitmap[bitmap_index];
  105.         bitcnt = 0;
  106.     } else 
  107.         bmap <<= 1;
  108.     }
  109. }
  110. /* --------------------------------
  111.  *    dump_tuple_internal - Dump a tuple in internal format
  112.  * --------------------------------
  113.  */
  114. void
  115. dump_tuple_internal(values, lengths, nfields)
  116.     char **values;
  117.      int *lengths;
  118.     int nfields;
  119. {
  120.     char     bitmap[MAXFIELDS];
  121.     int     bitmap_index = 0;
  122.     int     i;
  123.     unsigned     nbytes;        /* the number of bytes in bitmap */
  124.     char     bmap;        /* One byte of the bitmap */
  125.     int     bitcnt = 0;     /* number of bits examined in current byte */
  126.     int     vlen;        /* length of the current field value */
  127.     
  128.     nbytes = nfields / BYTELEN;
  129.     if ((nfields % BYTELEN) > 0) 
  130.     nbytes++;
  131.  
  132.     pq_getnchar(bitmap, 0, nbytes);
  133.     bmap = bitmap[bitmap_index];
  134.     
  135.     /* Read in all the attribute values. */
  136.     for (i = 0; i < nfields; i++) {
  137.     /* If the field value is absent, do nothing. */
  138.     if (!(bmap & 0200))
  139.         values[i] = NULL;
  140.     else {
  141.         /* For each attribute, we get:
  142.            Length (4 bytes),
  143.            Data (n bytes)
  144.            */
  145.         
  146.         vlen = pq_getint(4);
  147.         /* Allocate storage for the value. */
  148.         values[i] = pbuf_addValues(vlen + 1);
  149.         /* Read in the value. */
  150.         pq_getnchar(values[i], 0, vlen);
  151.         lengths[i] = vlen;
  152.         /* Put an end of string there to make life easier. */
  153.         values[i][vlen] = '\0';
  154.         pqdebug("%s", values[i]);
  155.     }
  156.  
  157.     /* Get the approriate bitmap. */
  158.     bitcnt++;
  159.     if (bitcnt == BYTELEN) {
  160.         bitmap_index++;
  161.         bmap = bitmap[bitmap_index];
  162.         bitcnt = 0;
  163.     } else 
  164.         bmap <<= 1;
  165.     }
  166. }
  167.  
  168. /* --------------------------------
  169.  *    finish_dump - End of a command (data stream)
  170.  * --------------------------------
  171.  */
  172. void
  173. finish_dump()
  174. {
  175.     char command[command_length];
  176.     int temp;
  177.     
  178.     temp = pq_getint(4);
  179.     pq_getstr(command, command_length);
  180.     
  181.     pqdebug("return code is %d",(char *)temp);
  182.     pqdebug("command is %s",command);
  183. }
  184.  
  185. /* --------------------------------
  186.  *    dump_data - Read and process the data stream from backend
  187.  * --------------------------------
  188.  */
  189. int 
  190. dump_data(portal_name, rule_p)
  191.     char *portal_name;
  192.     int rule_p;
  193. {
  194.     char      id[2];
  195.     char      pname[portal_name_length];
  196.     PortalEntry  *entry = NULL;
  197.     PortalBuffer *portal = NULL;
  198.     GroupBuffer  *group = NULL;
  199.     TypeBlock      *types = NULL;
  200.     TupleBlock      *tuples = NULL;
  201.  
  202.     int ntuples = 0;    /* the number of tuples in current group */
  203.     int nfields = 0;    /* the number of fields in current group */
  204.  
  205.     strcpy(pname, portal_name);
  206.  
  207.     /* If portal buffer is not allocated, do it now. */
  208.     /* if ((portal = PQparray(pname)) == NULL) */
  209.     entry = pbuf_setup(pname);
  210.     portal = entry->portal;
  211.     
  212.     /* If an asynchronized portal, set the flag. */
  213.     if (rule_p)
  214.     portal->rule_p = 1;
  215.  
  216.     /* Dump_data is called only when id[0] = 'T'. */
  217.     id[0] = 'T';
  218.     
  219.     /* Process the data stream. */
  220.     while (1) {
  221.     switch (id[0]) {
  222.     case 'T':
  223.         /* A new tuple group. */
  224.         
  225.         /* If this is not the first group, record the number of 
  226.            tuples in the previous group. */
  227.         if (group != NULL) {
  228.         group->no_tuples = ntuples;
  229.         /* Add the number of tuples in last group to the total. */
  230.         portal->no_tuples += ntuples;
  231.         }
  232.         
  233.         /* Increment the number of tuple groups. */
  234.         portal->no_groups++;
  235.         group = pbuf_addGroup(portal);
  236.         
  237.         /* Read in the number of fields (attributes) for this group. */
  238.         nfields = group->no_fields = pq_getint(2);
  239.         if (nfields > 0) {
  240.             types = group->types = pbuf_addTypes(nfields);
  241.             dump_type(types, nfields);
  242.         }
  243.         break;
  244.  
  245.     case 'B':
  246.         /* A tuple in internal (binary) format. */
  247.         
  248.         /* If no tuple block yet, allocate one. */
  249.         /* If the current block is full, allocate another one. */
  250.         if (group->tuples == NULL) {
  251.         tuples = group->tuples = pbuf_addTuples();
  252.         tuples->tuple_index = 0;
  253.         } else if (tuples->tuple_index == TupleBlockSize) {
  254.         tuples->next = pbuf_addTuples();
  255.         tuples = tuples->next;
  256.         tuples->tuple_index = 0;
  257.         }
  258.         
  259.         /* Allocate space for a tuple. */
  260.         tuples->values[tuples->tuple_index] =pbuf_addTuple(nfields);
  261.         tuples->lengths[tuples->tuple_index] = pbuf_addTupleValueLengths(nfields);
  262.  
  263.         /* Dump a tuple internal format. */
  264.         dump_tuple_internal(tuples->values[tuples->tuple_index],
  265.                 tuples->lengths[tuples->tuple_index],
  266.                 nfields);
  267.         ntuples++;
  268.         tuples->tuple_index++;
  269.         break;
  270.  
  271.     case 'D':
  272.         /* A tuple. */
  273.         
  274.         /* If no tuple block yet, allocate one. */
  275.         /* If the current block is full, allocate another one. */
  276.         if (group->tuples == NULL) {
  277.         tuples = group->tuples = pbuf_addTuples();
  278.         tuples->tuple_index = 0;
  279.         } else if (tuples->tuple_index == TupleBlockSize) {
  280.         tuples->next = pbuf_addTuples();
  281.         tuples = tuples->next;
  282.         tuples->tuple_index = 0;
  283.         }
  284.         
  285.         /* Allocate space for a tuple. */
  286.         tuples->values[tuples->tuple_index] =pbuf_addTuple(nfields);
  287.         tuples->lengths[tuples->tuple_index] = pbuf_addTupleValueLengths(nfields);
  288.         
  289.         /* Dump a tuple. */
  290.         dump_tuple(tuples->values[tuples->tuple_index],
  291.                tuples->lengths[tuples->tuple_index],
  292.                nfields);
  293.         ntuples++;
  294.         tuples->tuple_index++;
  295.         break;
  296. #if 0
  297.     case 'A':
  298.         /* Tuples returned by alerters. */
  299.         /* Finish up with the current portal. */
  300.         group->no_tuples = ntuples;
  301.         portal->no_tuples += ntuples;
  302.  
  303.         /* Process the asynchronized portal. */
  304.         /* This part of the protocol is not very clear. */
  305.         pq_getint(4);
  306.         pq_getstr(pname, portal_name_length);
  307.         pqdebug("Asynchronized portal: %s", pname);
  308.         
  309.         entry = pbuf_setup(pname);
  310.         portal = entry->portal;
  311.         portal->rule_p = 1;
  312.         group = NULL;
  313.         ntuples = 0;
  314.         nfields = 0;
  315.         tuples = NULL;
  316.         break;
  317. #endif
  318.  
  319.     case 'C':
  320.         /* Command, end of the data stream. */
  321.         /* Record the number of tuples in the last group. */
  322.         group->no_tuples = ntuples;
  323.         portal->no_tuples += ntuples;
  324.         finish_dump();
  325.         return(1);
  326.         
  327.     case 'E':
  328.         /* YES - THIS CAN HAPPEN - for instance when dynamic loading fails!!! */
  329.  
  330.         pq_getstr(PQerrormsg, error_msg_length);
  331.         pqdebug("%s error encountered.", PQerrormsg);
  332.  
  333.         /*
  334.          * use PQerrormsg[4] because there is garbage in the first four bytes..
  335.          */
  336.         bcopy(&PQerrormsg[4],PQerrormsg,strlen(PQerrormsg)-4);
  337.         fprintf(stderr,"%s\n", PQerrormsg);
  338.         fflush(stderr);
  339.         return(-1);
  340.     case 'N':
  341.         pq_getstr(PQerrormsg, error_msg_length);
  342.         pqdebug("%s error encountered.", PQerrormsg);
  343.  
  344.         /*
  345.          * use errormsg[4] because there is garbage in the first four bytes..
  346.          */
  347.         bcopy(&PQerrormsg[4],PQerrormsg,strlen(PQerrormsg)-4);
  348.         fprintf(stderr,"%s\n", PQerrormsg);
  349.         fflush(stderr);
  350.         break;
  351.     default:
  352.         {
  353.         char s[40];
  354.  
  355.         /* This should never happen. */
  356.         sprintf(s, "Unexpected identfier in dump_data: %c", id[0]);
  357.         libpq_raise(&ProtocolError, form((int)s));
  358.         }
  359.     }
  360.     
  361.         pq_getnchar(id,0,1); 
  362.         read_remark(id);
  363.     pqdebug("The identifier is: %c", (char *)id[0]);
  364.     }
  365. }
  366.