Logo Search packages:      
Sourcecode: psqlodbc version File versions

columninfo.c

/*-------
 * Module:              columninfo.c
 *
 * Description:         This module contains routines related to
 *                            reading and storing the field information from a query.
 *
 * Classes:             ColumnInfoClass (Functions prefix: "CI_")
 *
 * API functions: none
 *
 * Comments:            See "notice.txt" for copyright and license information.
 *-------
 */

#include "pgtypes.h"
#include "columninfo.h"

#include "connection.h"
#include "socket.h"
#include <stdlib.h>
#include <string.h>
#include "pgapifunc.h"

ColumnInfoClass *
CI_Constructor()
{
      ColumnInfoClass *rv;

      rv = (ColumnInfoClass *) malloc(sizeof(ColumnInfoClass));

      if (rv)
      {
            rv->num_fields = 0;
            rv->name = NULL;
            rv->adtid = NULL;
            rv->adtsize = NULL;
            rv->display_size = NULL;
            rv->atttypmod = NULL;
      }

      return rv;
}


void
CI_Destructor(ColumnInfoClass *self)
{
      CI_free_memory(self);

      free(self);
}


/*
 *    Read in field descriptions.
 *    If self is not null, then also store the information.
 *    If self is null, then just read, don't store.
 */
char
CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
{
      Int2        lf;
      int               new_num_fields;
      Oid               new_adtid;
      Int2        new_adtsize;
      Int4        new_atttypmod = -1;

      /* COLUMN_NAME_STORAGE_LEN may be sufficient but for safety */
      char        new_field_name[2 * COLUMN_NAME_STORAGE_LEN + 1];
      SocketClass *sock;
      ConnInfo   *ci;

      sock = CC_get_socket(conn);
      ci = &conn->connInfo;

      /* at first read in the number of fields that are in the query */
      new_num_fields = (Int2) SOCK_get_int(sock, sizeof(Int2));

      mylog("num_fields = %d\n", new_num_fields);

      if (self)
            /* according to that allocate memory */
            CI_set_num_fields(self, new_num_fields);

      /* now read in the descriptions */
      for (lf = 0; lf < new_num_fields; lf++)
      {
            SOCK_get_string(sock, new_field_name, 2 * COLUMN_NAME_STORAGE_LEN);
            new_adtid = (Oid) SOCK_get_int(sock, 4);
            new_adtsize = (Int2) SOCK_get_int(sock, 2);

            /* If 6.4 protocol, then read the atttypmod field */
            if (PG_VERSION_GE(conn, 6.4))
            {
                  mylog("READING ATTTYPMOD\n");
                  new_atttypmod = (Int4) SOCK_get_int(sock, 4);

                  /* Subtract the header length */
                  switch (new_adtid)
                  {
                        case PG_TYPE_DATETIME:
                        case PG_TYPE_TIMESTAMP_NO_TMZONE:
                        case PG_TYPE_TIME:
                        case PG_TYPE_TIME_WITH_TMZONE:
                              break;
                        default:
                              new_atttypmod -= 4;
                  }
                  if (new_atttypmod < 0)
                        new_atttypmod = -1;

            }

            mylog("CI_read_fields: fieldname='%s', adtid=%d, adtsize=%d, atttypmod=%d\n", new_field_name, new_adtid, new_adtsize, new_atttypmod);

            if (self)
                  CI_set_field_info(self, lf, new_field_name, new_adtid, new_adtsize, new_atttypmod);
      }

      return (SOCK_get_errcode(sock) == 0);
}


void
CI_free_memory(ColumnInfoClass *self)
{
      register Int2 lf;
      int               num_fields = self->num_fields;

      for (lf = 0; lf < num_fields; lf++)
      {
            if (self->name[lf])
            {
                  free(self->name[lf]);
                  self->name[lf] = NULL;
            }
      }

      /* Safe to call even if null */
      self->num_fields = 0;
      if (self->name)
            free(self->name);
      self->name = NULL;
      if (self->adtid)
            free(self->adtid);
      self->adtid = NULL;
      if (self->adtsize)
            free(self->adtsize);
      self->adtsize = NULL;
      if (self->display_size)
            free(self->display_size);
      self->display_size = NULL;

      if (self->atttypmod)
            free(self->atttypmod);
      self->atttypmod = NULL;
}


void
CI_set_num_fields(ColumnInfoClass *self, int new_num_fields)
{
      CI_free_memory(self);         /* always safe to call */

      self->num_fields = new_num_fields;

      self->name = (char **) malloc(sizeof(char *) * self->num_fields);
      memset(self->name, 0, sizeof(char *) * self->num_fields);
      self->adtid = (Oid *) malloc(sizeof(Oid) * self->num_fields);
      self->adtsize = (Int2 *) malloc(sizeof(Int2) * self->num_fields);
      self->display_size = (Int2 *) malloc(sizeof(Int2) * self->num_fields);
      self->atttypmod = (Int4 *) malloc(sizeof(Int4) * self->num_fields);
}


void
CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name,
                          Oid new_adtid, Int2 new_adtsize, Int4 new_atttypmod)
{
      /* check bounds */
      if ((field_num < 0) || (field_num >= self->num_fields))
            return;

      /* store the info */
      self->name[field_num] = strdup(new_name);
      self->adtid[field_num] = new_adtid;
      self->adtsize[field_num] = new_adtsize;
      self->atttypmod[field_num] = new_atttypmod;

      self->display_size[field_num] = 0;
}

Generated by  Doxygen 1.6.0   Back to index