Re: Re: [ODBC] Cleanup of ODBC - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: Re: [ODBC] Cleanup of ODBC
Date
Msg-id 200103281659.LAA28125@candle.pha.pa.us
Whole thread Raw
In response to Re: [ODBC] Cleanup of ODBC  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-patches
OK, here is the ODBC patch I am holding.  I will run pgindent after I
apply it to 7.2 branch to properly wrap the comments.


> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > I am working to clean up the comments in ODBC, and remove some blank
> > lines that make no sense being there.  This will not affect the code in
> > any way.  I should commit in a few hours.
>
> Is it really appropriate to be doing this sort of work post-RC1?
> I see no gain and a nontrivial risk that you will break something
> without knowing it (and without providing adequate time to test it).
>
> It's bad enough to be running pgindent at this late stage of the cycle,
> but at least pgindent is automated and relatively unlikely to make
> errors.  Massive hand edits are another story.
>
> In short: save it for 7.2.
>
>             regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
>


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
Index: src/interfaces/odbc/bind.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/bind.c,v
retrieving revision 1.23
diff -c -r1.23 bind.c
*** src/interfaces/odbc/bind.c    2001/03/27 04:00:53    1.23
--- src/interfaces/odbc/bind.c    2001/03/28 16:53:12
***************
*** 1,4 ****
! /* Module:            bind.c
   *
   * Description:        This module contains routines related to binding
   *                    columns and parameters.
--- 1,5 ----
! /*-------
!  * Module:            bind.c
   *
   * Description:        This module contains routines related to binding
   *                    columns and parameters.
***************
*** 9,15 ****
   *                    SQLParamOptions(NI)
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 10,16 ----
   *                    SQLParamOptions(NI)
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 112,119 ****
          }
      }

!     ipar--;                        /* use zero based column numbers for the
!                                  * below part */

      /* store the given info */
      stmt->parameters[ipar].buflen = cbValueMax;
--- 113,120 ----
          }
      }

!     /* use zero based column numbers for the below part */
!     ipar--;

      /* store the given info */
      stmt->parameters[ipar].buflen = cbValueMax;
***************
*** 152,161 ****

      return SQL_SUCCESS;
  }
-
- /*        -        -        -        -        -        -        -        -        - */

! /*        Associate a user-supplied buffer with a database column. */
  RETCODE SQL_API
  SQLBindCol(
             HSTMT hstmt,
--- 153,160 ----

      return SQL_SUCCESS;
  }

! /*  Associate a user-supplied buffer with a database column. */
  RETCODE SQL_API
  SQLBindCol(
             HSTMT hstmt,
***************
*** 192,198 ****
      /* If the bookmark column is being bound, then just save it */
      if (icol == 0)
      {
-
          if (rgbValue == NULL)
          {
              stmt->bookmark.buffer = NULL;
--- 191,196 ----
***************
*** 215,224 ****
          return SQL_SUCCESS;
      }

!     /* allocate enough bindings if not already done */
!     /* Most likely, execution of a statement would have setup the  */
!     /* necessary bindings. But some apps call BindCol before any */
!     /* statement is executed. */
      if (icol > stmt->bindings_allocated)
          extend_bindings(stmt, icol);

--- 213,224 ----
          return SQL_SUCCESS;
      }

!     /*
!      * Allocate enough bindings if not already done.
!      * Most likely, execution of a statement would have setup the
!      * necessary bindings. But some apps call BindCol before any
!      * statement is executed.
!      */
      if (icol > stmt->bindings_allocated)
          extend_bindings(stmt, icol);

***************
*** 231,238 ****
          return SQL_ERROR;
      }

!     icol--;                        /* use zero based col numbers from here
!                                  * out */

      /* Reset for SQLGetData */
      stmt->bindings[icol].data_left = -1;
--- 231,238 ----
          return SQL_ERROR;
      }

!     /* use zero based col numbers from here out */
!     icol--;

      /* Reset for SQLGetData */
      stmt->bindings[icol].data_left = -1;
***************
*** 259,272 ****
      return SQL_SUCCESS;
  }

- /*        -        -        -        -        -        -        -        -        - */

! /*    Returns the description of a parameter marker. */
! /*    This function is listed as not being supported by SQLGetFunctions() because it is  */
! /*    used to describe "parameter markers" (not bound parameters), in which case,  */
! /*    the dbms should return info on the markers.  Since Postgres doesn't support that, */
! /*    it is best to say this function is not supported and let the application assume a  */
! /*    data type (most likely varchar). */

  RETCODE SQL_API
  SQLDescribeParam(
--- 259,273 ----
      return SQL_SUCCESS;
  }


! /*
!  *    Returns the description of a parameter marker.
!  *    This function is listed as not being supported by SQLGetFunctions() because it is
!  *    used to describe "parameter markers" (not bound parameters), in which case,
!  *    the dbms should return info on the markers.  Since Postgres doesn't support that,
!  *    it is best to say this function is not supported and let the application assume a
!  *    data type (most likely varchar).
!  */

  RETCODE SQL_API
  SQLDescribeParam(
***************
*** 318,327 ****
      return SQL_SUCCESS;
  }

! /*        -        -        -        -        -        -        -        -        - */

- /*        Sets multiple values (arrays) for the set of parameter markers. */
-
  RETCODE SQL_API
  SQLParamOptions(
                  HSTMT hstmt,
--- 319,326 ----
      return SQL_SUCCESS;
  }

! /*    Sets multiple values (arrays) for the set of parameter markers. */

  RETCODE SQL_API
  SQLParamOptions(
                  HSTMT hstmt,
***************
*** 336,350 ****
      return SQL_ERROR;
  }

- /*        -        -        -        -        -        -        -        -        - */

! /*    This function should really talk to the dbms to determine the number of  */
! /*    "parameter markers" (not bound parameters) in the statement.  But, since */
! /*    Postgres doesn't support that, the driver should just count the number of markers */
! /*    and return that.  The reason the driver just can't say this function is unsupported */
! /*    like it does for SQLDescribeParam is that some applications don't care and try  */
! /*    to call it anyway. */
! /*    If the statement does not have parameters, it should just return 0. */
  RETCODE SQL_API
  SQLNumParams(
               HSTMT hstmt,
--- 335,350 ----
      return SQL_ERROR;
  }


! /*
!  *    This function should really talk to the dbms to determine the number of
!  *    "parameter markers" (not bound parameters) in the statement.  But, since
!  *    Postgres doesn't support that, the driver should just count the number of markers
!  *    and return that.  The reason the driver just can't say this function is unsupported
!  *    like it does for SQLDescribeParam is that some applications don't care and try
!  *    to call it anyway.
!  *    If the statement does not have parameters, it should just return 0.
!  */
  RETCODE SQL_API
  SQLNumParams(
               HSTMT hstmt,
***************
*** 382,391 ****
      }
      else
      {
-
          for (i = 0; i < strlen(stmt->statement); i++)
          {
-
              if (stmt->statement[i] == '?' && !in_quote)
                  (*pcpar)++;
              else
--- 382,389 ----
***************
*** 394,405 ****
                      in_quote = (in_quote ? FALSE : TRUE);
              }
          }
-
          return SQL_SUCCESS;
      }
  }

! /********************************************************************
   *     Bindings Implementation
   */
  BindInfoClass *
--- 392,402 ----
                      in_quote = (in_quote ? FALSE : TRUE);
              }
          }
          return SQL_SUCCESS;
      }
  }

! /*
   *     Bindings Implementation
   */
  BindInfoClass *
***************
*** 432,442 ****

      mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated,
num_columns);

!     /* if we have too few, allocate room for more, and copy the old */
!     /* entries into the new structure */
      if (stmt->bindings_allocated < num_columns)
      {
-
          new_bindings = create_empty_bindings(num_columns);
          if (!new_bindings)
          {
--- 429,440 ----

      mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated,
num_columns);

!     /*
!      * if we have too few, allocate room for more, and copy the old
!      * entries into the new structure
!      */
      if (stmt->bindings_allocated < num_columns)
      {
          new_bindings = create_empty_bindings(num_columns);
          if (!new_bindings)
          {
***************
*** 461,471 ****

          stmt->bindings = new_bindings;
          stmt->bindings_allocated = num_columns;
-
      }
!     /* There is no reason to zero out extra bindings if there are */
!     /* more than needed.  If an app has allocated extra bindings,  */
!     /* let it worry about it by unbinding those columns. */

      /* SQLBindCol(1..) ... SQLBindCol(10...)   # got 10 bindings */
      /* SQLExecDirect(...)  # returns 5 cols */
--- 459,470 ----

          stmt->bindings = new_bindings;
          stmt->bindings_allocated = num_columns;
      }
!     /*
!      * There is no reason to zero out extra bindings if there are
!      * more than needed.  If an app has allocated extra bindings,
!      * let it worry about it by unbinding those columns.
!      */

      /* SQLBindCol(1..) ... SQLBindCol(10...)   # got 10 bindings */
      /* SQLExecDirect(...)  # returns 5 cols */
Index: src/interfaces/odbc/columninfo.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/columninfo.c,v
retrieving revision 1.18
diff -c -r1.18 columninfo.c
*** src/interfaces/odbc/columninfo.c    2001/03/27 04:00:53    1.18
--- src/interfaces/odbc/columninfo.c    2001/03/28 16:53:12
***************
*** 1,4 ****
! /* Module:            columninfo.c
   *
   * Description:        This module contains routines related to
   *                    reading and storing the field information from a query.
--- 1,5 ----
! /*-------
!  * Module:            columninfo.c
   *
   * Description:        This module contains routines related to
   *                    reading and storing the field information from a query.
***************
*** 8,14 ****
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #include "columninfo.h"
--- 9,15 ----
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #include "columninfo.h"
***************
*** 45,54 ****
      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)
  {
--- 46,56 ----
      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)
  {
***************
*** 77,83 ****
      /* now read in the descriptions */
      for (lf = 0; lf < new_num_fields; lf++)
      {
-
          SOCK_get_string(sock, new_field_name, MAX_MESSAGE_LEN);
          new_adtid = (Oid) SOCK_get_int(sock, 4);
          new_adtsize = (Int2) SOCK_get_int(sock, 2);
--- 79,84 ----
***************
*** 85,91 ****
          /* 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);

--- 86,91 ----
***************
*** 106,112 ****
  }


-
  void
  CI_free_memory(ColumnInfoClass *self)
  {
--- 106,111 ----
***************
*** 146,152 ****
  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;
--- 145,150 ----
Index: src/interfaces/odbc/connection.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/connection.c,v
retrieving revision 1.27
diff -c -r1.27 connection.c
*** src/interfaces/odbc/connection.c    2001/03/27 04:00:53    1.27
--- src/interfaces/odbc/connection.c    2001/03/28 16:53:13
***************
*** 1,4 ****
! /* Module:            connection.c
   *
   * Description:        This module contains routines related to
   *                    connecting to and disconnecting from the Postgres DBMS.
--- 1,5 ----
! /*------
!  * Module:            connection.c
   *
   * Description:        This module contains routines related to
   *                    connecting to and disconnecting from the Postgres DBMS.
***************
*** 9,15 ****
   *                    SQLBrowseConnect(NI)
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */
  /* Multibyte support    Eiji Tokuya 2001-03-15 */

--- 10,16 ----
   *                    SQLBrowseConnect(NI)
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */
  /* Multibyte support    Eiji Tokuya 2001-03-15 */

***************
*** 83,90 ****
  }


- /*        -        -        -        -        -        -        -        -        - */
-
  RETCODE SQL_API
  SQLConnect(
             HDBC hdbc,
--- 84,89 ----
***************
*** 140,146 ****
      return SQL_SUCCESS;
  }

- /*        -        -        -        -        -        -        -        -        - */

  RETCODE SQL_API
  SQLBrowseConnect(
--- 139,144 ----
***************
*** 158,164 ****
      return SQL_SUCCESS;
  }

- /*        -        -        -        -        -        -        -        -        - */

  /* Drop any hstmts open on hdbc and disconnect from database */
  RETCODE SQL_API
--- 156,161 ----
***************
*** 199,206 ****
  }


- /*        -        -        -        -        -        -        -        -        - */
-
  RETCODE SQL_API
  SQLFreeConnect(
                 HDBC hdbc)
--- 196,201 ----
***************
*** 235,244 ****


  /*
! *
! *        IMPLEMENTATION CONNECTION CLASS
! *
! */

  ConnectionClass *
  CC_Constructor()
--- 230,237 ----


  /*
!  *        IMPLEMENTATION CONNECTION CLASS
!  */

  ConnectionClass *
  CC_Constructor()
***************
*** 249,255 ****

      if (rv != NULL)
      {
-
          rv->henv = NULL;        /* not yet associated with an environment */

          rv->errormsg = NULL;
--- 242,247 ----
***************
*** 301,307 ****
  char
  CC_Destructor(ConnectionClass *self)
  {
-
      mylog("enter CC_Destructor, self=%u\n", self);

      if (self->status == CONN_EXECUTING)
--- 293,298 ----
***************
*** 373,380 ****
      self->errormsg_created = FALSE;
  }

! /*    Used to cancel a transaction */
! /*    We are almost always in the middle of a transaction. */
  char
  CC_abort(ConnectionClass *self)
  {
--- 364,373 ----
      self->errormsg_created = FALSE;
  }

! /*
!  *    Used to cancel a transaction.
!  *    We are almost always in the middle of a transaction.
!  */
  char
  CC_abort(ConnectionClass *self)
  {
***************
*** 434,440 ****
          stmt = self->stmts[i];
          if (stmt)
          {
-
              stmt->hdbc = NULL;    /* prevent any more dbase interactions */

              SC_Destructor(stmt);
--- 427,432 ----
***************
*** 521,527 ****

      else
      {
-
          qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d,
max_longvarchar_size=%d\n",
               POSTGRESDRIVERVERSION,
               globals.fetch_max,
--- 513,518 ----
***************
*** 646,659 ****
      mylog("gonna do authentication\n");


!     /* *************************************************** */
!     /* Now get the authentication request from backend */
!     /* *************************************************** */

      if (!PROTOCOL_62(ci))
          do
          {
-
              if (do_password)
                  beresp = 'R';
              else
--- 637,649 ----
      mylog("gonna do authentication\n");


!     /*
!      * Now get the authentication request from backend
!      */

      if (!PROTOCOL_62(ci))
          do
          {
              if (do_password)
                  beresp = 'R';
              else
***************
*** 743,750 ****

      CC_clear_error(self);        /* clear any password error */

!     /* send an empty query in order to find out whether the specified */
!     /* database really exists on the server machine */
      mylog("sending an empty query...\n");

      res = CC_send_query(self, " ", NULL);
--- 733,742 ----

      CC_clear_error(self);        /* clear any password error */

!     /*
!      * send an empty query in order to find out whether the specified
!      * database really exists on the server machine
!      */
      mylog("sending an empty query...\n");

      res = CC_send_query(self, " ", NULL);
***************
*** 764,772 ****

      CC_set_translation(self);

!     /**********************************************/
!     /*******   Send any initial settings  *********/
!     /**********************************************/

      /*
       * Since these functions allocate statements, and since the connection
--- 756,764 ----

      CC_set_translation(self);

!     /*
!      *    Send any initial settings
!      */

      /*
       * Since these functions allocate statements, and since the connection
***************
*** 838,846 ****
      return FALSE;
  }

! /*    Create a more informative error message by concatenating the connection
!     error message with its socket error message.
! */
  char *
  CC_create_errormsg(ConnectionClass *self)
  {
--- 830,839 ----
      return FALSE;
  }

! /*
!  *    Create a more informative error message by concatenating the connection
!  *    error message with its socket error message.
!  */
  char *
  CC_create_errormsg(ConnectionClass *self)
  {
***************
*** 897,910 ****
  }


! /*    The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
!     the same existing QResultClass (this occurs when the tuple cache is depleted and
!     needs to be re-filled).
!
!     The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
!     (i.e., C3326857) for SQL select statements.  This cursor is then used in future
!     'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
! */
  QResultClass *
  CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
  {
--- 890,904 ----
  }


! /*
!  *    The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
!  *    the same existing QResultClass (this occurs when the tuple cache is depleted and
!  *    needs to be re-filled).
!  *
!  *    The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
!  *    (i.e., C3326857) for SQL select statements.  This cursor is then used in future
!  *    'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
!  */
  QResultClass *
  CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
  {
***************
*** 914,923 ****
      int            id;
      SocketClass *sock = self->sock;
      static char msgbuffer[MAX_MESSAGE_LEN + 1];
!     char        cmdbuffer[MAX_MESSAGE_LEN + 1]; /* QR_set_command() dups
!                                                  * this string so dont
!                                                  * need static */
!

      mylog("send_query(): conn=%u, query='%s'\n", self, query);
      qlog("conn=%u, query='%s'\n", self, query);
--- 908,915 ----
      int            id;
      SocketClass *sock = self->sock;
      static char msgbuffer[MAX_MESSAGE_LEN + 1];
!     /* QR_set_command() dups this string so don't need static */
!     char        cmdbuffer[MAX_MESSAGE_LEN + 1];

      mylog("send_query(): conn=%u, query='%s'\n", self, query);
      qlog("conn=%u, query='%s'\n", self, query);
***************
*** 1003,1009 ****
                  }
                  else
                  {
-
                      char        clear = 0;

                      mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
--- 995,1000 ----
***************
*** 1239,1245 ****

      for (i = 0; i < nargs; ++i)
      {
-
          mylog("  arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint,
args[i].u.integer,args[i].u.ptr); 

          SOCK_put_int(sock, args[i].len, 4);
--- 1230,1235 ----
***************
*** 1371,1379 ****

      mylog("%s: entering...\n", func);

! /*    This function must use the local odbc API functions since the odbc state
!     has not transitioned to "connected" yet.
! */

      result = SQLAllocStmt(self, &hstmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
--- 1361,1370 ----

      mylog("%s: entering...\n", func);

! /*
!  *    This function must use the local odbc API functions since the odbc state
!  *    has not transitioned to "connected" yet.
!  */

      result = SQLAllocStmt(self, &hstmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
***************
*** 1455,1464 ****
      return status;
  }

! /*    This function is just a hack to get the oid of our Large Object oid type.
!     If a real Large Object oid type is made part of Postgres, this function
!     will go away and the define 'PG_TYPE_LO' will be updated.
! */
  void
  CC_lookup_lo(ConnectionClass *self)
  {
--- 1446,1456 ----
      return status;
  }

! /*
!  *    This function is just a hack to get the oid of our Large Object oid type.
!  *    If a real Large Object oid type is made part of Postgres, this function
!  *    will go away and the define 'PG_TYPE_LO' will be updated.
!  */
  void
  CC_lookup_lo(ConnectionClass *self)
  {
***************
*** 1469,1477 ****

      mylog("%s: entering...\n", func);

! /*    This function must use the local odbc API functions since the odbc state
!     has not transitioned to "connected" yet.
! */
      result = SQLAllocStmt(self, &hstmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
          return;
--- 1461,1470 ----

      mylog("%s: entering...\n", func);

! /*
!  *    This function must use the local odbc API functions since the odbc state
!  *    has not transitioned to "connected" yet.
!  */
      result = SQLAllocStmt(self, &hstmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
          return;
***************
*** 1504,1513 ****
      result = SQLFreeStmt(hstmt, SQL_DROP);
  }

! /*    This function initializes the version of PostgreSQL from
!     connInfo.protocol that we're connected to.
!     h-inoue 01-2-2001
! */
  void
  CC_initialize_pg_version(ConnectionClass *self)
  {
--- 1497,1507 ----
      result = SQLFreeStmt(hstmt, SQL_DROP);
  }

! /*
!  *    This function initializes the version of PostgreSQL from
!  *    connInfo.protocol that we're connected to.
!  *    h-inoue 01-2-2001
!  */
  void
  CC_initialize_pg_version(ConnectionClass *self)
  {
***************
*** 1532,1541 ****
      }
  }

! /*    This function gets the version of PostgreSQL that we're connected to.
!     This is used to return the correct info in SQLGetInfo
!     DJP - 25-1-2001
! */
  void
  CC_lookup_pg_version(ConnectionClass *self)
  {
--- 1526,1536 ----
      }
  }

! /*
!  *    This function gets the version of PostgreSQL that we're connected to.
!  *    This is used to return the correct info in SQLGetInfo
!  *    DJP - 25-1-2001
!  */
  void
  CC_lookup_pg_version(ConnectionClass *self)
  {
***************
*** 1549,1557 ****

      mylog("%s: entering...\n", func);

! /*    This function must use the local odbc API functions since the odbc state
!     has not transitioned to "connected" yet.
! */
      result = SQLAllocStmt(self, &hstmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
          return;
--- 1544,1553 ----

      mylog("%s: entering...\n", func);

! /*
!  *    This function must use the local odbc API functions since the odbc state
!  *    has not transitioned to "connected" yet.
!  */
      result = SQLAllocStmt(self, &hstmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
          return;
***************
*** 1579,1586 ****
          return;
      }

!     /* Extract the Major and Minor numbers from the string. */
!     /* This assumes the string starts 'Postgresql X.X' */
      strcpy(szVersion, "0.0");
      if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2)
      {
--- 1575,1584 ----
          return;
      }

!     /*
!      *    Extract the Major and Minor numbers from the string.
!      *     This assumes the string starts 'Postgresql X.X'
!      */
      strcpy(szVersion, "0.0");
      if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2)
      {
Index: src/interfaces/odbc/convert.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/convert.c,v
retrieving revision 1.35
diff -c -r1.35 convert.c
*** src/interfaces/odbc/convert.c    2001/03/27 04:00:53    1.35
--- src/interfaces/odbc/convert.c    2001/03/28 16:53:14
***************
*** 1,4 ****
! /* Module:           convert.c
   *
   * Description:    This module contains routines related to
   *                   converting parameters and columns into requested data types.
--- 1,5 ----
! /*-------
!  * Module:           convert.c
   *
   * Description:    This module contains routines related to
   *                   converting parameters and columns into requested data types.
***************
*** 12,18 ****
   * API functions:  none
   *
   * Comments:       See "notice.txt" for copyright and license information.
!  *
   */
  /* Multibyte support  Eiji Tokuya    2001-03-15    */

--- 13,19 ----
   * API functions:  none
   *
   * Comments:       See "notice.txt" for copyright and license information.
!  *-------
   */
  /* Multibyte support  Eiji Tokuya    2001-03-15    */

***************
*** 63,73 ****

  extern GLOBAL_VALUES globals;

! /*    How to map ODBC scalar functions {fn func(args)} to Postgres
!  *    This is just a simple substitution
!  *    List augmented from
!  *     http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
!  * - thomas 2000-04-03
   */
  char       *mapFuncs[][2] = {
  /*    { "ASCII",         "ascii"      }, */
--- 64,74 ----

  extern GLOBAL_VALUES globals;

! /*
!  *    How to map ODBC scalar functions {fn func(args)} to Postgres.
!  *    This is just a simple substitution.  List augmented from:
!  *    http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
!  *     - thomas 2000-04-03
   */
  char       *mapFuncs[][2] = {
  /*    { "ASCII",         "ascii"      }, */
***************
*** 140,160 ****
  unsigned int conv_from_hex(unsigned char *s);
  char       *conv_to_octal(unsigned char val);

! /********        A Guide for date/time/timestamp conversions    **************

-             field_type        fCType                Output
-             ----------        ------                ----------
-             PG_TYPE_DATE    SQL_C_DEFAULT        SQL_C_DATE
-             PG_TYPE_DATE    SQL_C_DATE            SQL_C_DATE
-             PG_TYPE_DATE    SQL_C_TIMESTAMP        SQL_C_TIMESTAMP        (time = 0 (midnight))
-             PG_TYPE_TIME    SQL_C_DEFAULT        SQL_C_TIME
-             PG_TYPE_TIME    SQL_C_TIME            SQL_C_TIME
-             PG_TYPE_TIME    SQL_C_TIMESTAMP        SQL_C_TIMESTAMP        (date = current date)
-             PG_TYPE_ABSTIME SQL_C_DEFAULT        SQL_C_TIMESTAMP
-             PG_TYPE_ABSTIME SQL_C_DATE            SQL_C_DATE            (time is truncated)
-             PG_TYPE_ABSTIME SQL_C_TIME            SQL_C_TIME            (date is truncated)
-             PG_TYPE_ABSTIME SQL_C_TIMESTAMP        SQL_C_TIMESTAMP
- ******************************************************************************/


  /*    This is called by SQLFetch() */
--- 141,164 ----
  unsigned int conv_from_hex(unsigned char *s);
  char       *conv_to_octal(unsigned char val);

! /*---------
!  *            A Guide for date/time/timestamp conversions
!  *
!  *            field_type        fCType                Output
!  *            ----------        ------                ----------
!  *            PG_TYPE_DATE    SQL_C_DEFAULT        SQL_C_DATE
!  *            PG_TYPE_DATE    SQL_C_DATE            SQL_C_DATE
!  *            PG_TYPE_DATE    SQL_C_TIMESTAMP        SQL_C_TIMESTAMP        (time = 0 (midnight))
!  *            PG_TYPE_TIME    SQL_C_DEFAULT        SQL_C_TIME
!  *            PG_TYPE_TIME    SQL_C_TIME            SQL_C_TIME
!  *            PG_TYPE_TIME    SQL_C_TIMESTAMP        SQL_C_TIMESTAMP        (date = current date)
!  *            PG_TYPE_ABSTIME SQL_C_DEFAULT        SQL_C_TIMESTAMP
!  *            PG_TYPE_ABSTIME SQL_C_DATE            SQL_C_DATE            (time is truncated)
!  *            PG_TYPE_ABSTIME SQL_C_TIME            SQL_C_TIME            (date is truncated)
!  *            PG_TYPE_ABSTIME SQL_C_TIMESTAMP        SQL_C_TIMESTAMP
!  *---------
!  */



  /*    This is called by SQLFetch() */
***************
*** 186,202 ****
      int            result = COPY_OK;
      char        tempBuf[TEXT_FIELD_SIZE + 5];

! /*    rgbValueOffset is *ONLY* for character and binary data */
! /*    pcbValueOffset is for computing any pcbValue location */

      if (bind_size > 0)
      {
-
          pcbValueOffset = rgbValueOffset = (bind_size * bind_row);
      }
      else
      {
-
          pcbValueOffset = bind_row * sizeof(SDWORD);
          rgbValueOffset = bind_row * cbValueMax;

--- 190,207 ----
      int            result = COPY_OK;
      char        tempBuf[TEXT_FIELD_SIZE + 5];

!     /*---------
!      *    rgbValueOffset is *ONLY* for character and binary data.
!      *    pcbValueOffset is for computing any pcbValue location
!      *---------
!      */

      if (bind_size > 0)
      {
          pcbValueOffset = rgbValueOffset = (bind_size * bind_row);
      }
      else
      {
          pcbValueOffset = bind_row * sizeof(SDWORD);
          rgbValueOffset = bind_row * cbValueMax;

***************
*** 214,227 ****

      if (!value)
      {
!         /* handle a null just by returning SQL_NULL_DATA in pcbValue, */
!         /* and doing nothing to the buffer.                              */
          if (pcbValue)
              *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA;
          return COPY_OK;
      }

-
      if (stmt->hdbc->DataSourceToDriver != NULL)
      {
          int            length = strlen(value);
--- 219,233 ----

      if (!value)
      {
!         /*
!          * handle a null just by returning SQL_NULL_DATA in pcbValue,
!          * and doing nothing to the buffer.
!          */
          if (pcbValue)
              *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA;
          return COPY_OK;
      }

      if (stmt->hdbc->DataSourceToDriver != NULL)
      {
          int            length = strlen(value);
***************
*** 233,253 ****
                                         NULL, 0, NULL);
      }

!
!     /********************************************************************
!         First convert any specific postgres types into more
!         useable data.
!
!         NOTE: Conversions from PG char/varchar of a date/time/timestamp
!         value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
!     *********************************************************************/
      switch (field_type)
      {
!
!             /*
!              * $$$ need to add parsing for date/time/timestamp strings in
!              * PG_TYPE_CHAR,VARCHAR $$$
!              */
          case PG_TYPE_DATE:
              sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d);
              break;
--- 239,257 ----
                                         NULL, 0, NULL);
      }

!     /*
!      *    First convert any specific postgres types into more
!      *    useable data.
!      *
!      *    NOTE: Conversions from PG char/varchar of a date/time/timestamp
!      *    value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
!      */
      switch (field_type)
      {
!         /*
!          * $$$ need to add parsing for date/time/timestamp strings in
!          * PG_TYPE_CHAR,VARCHAR $$$
!          */
          case PG_TYPE_DATE:
              sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d);
              break;
***************
*** 260,272 ****
          case PG_TYPE_DATETIME:
          case PG_TYPE_TIMESTAMP:
              if (strnicmp(value, "invalid", 7) != 0)
-             {
                  sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, &st.d, &st.hh, &st.mm, &st.ss);
-
-             }
              else
!             {                    /* The timestamp is invalid so set
!                                  * something conspicuous, like the epoch */
                  t = 0;
                  tim = localtime(&t);
                  st.m = tim->tm_mon + 1;
--- 264,276 ----
          case PG_TYPE_DATETIME:
          case PG_TYPE_TIMESTAMP:
              if (strnicmp(value, "invalid", 7) != 0)
                  sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, &st.d, &st.hh, &st.mm, &st.ss);
              else
!             {
!                 /*
!                  * The timestamp is invalid so set
!                  * something conspicuous, like the epoch
!                  */
                  t = 0;
                  tim = localtime(&t);
                  st.m = tim->tm_mon + 1;
***************
*** 289,295 ****
              }
              break;

!             /* This is for internal use by SQLStatistics() */
          case PG_TYPE_INT2VECTOR:
              {
                  int            nval,
--- 293,299 ----
              }
              break;

!         /* This is for internal use by SQLStatistics() */
          case PG_TYPE_INT2VECTOR:
              {
                  int            nval,
***************
*** 368,382 ****
          mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);
      }

-
      rgbValueBindRow = (char *) rgbValue + rgbValueOffset;

      if (fCType == SQL_C_CHAR)
      {
-
-
          /* Special character formatting as required */
-
          /*
           * These really should return error if cbValueMax is not big
           * enough.
--- 372,382 ----
***************
*** 455,461 ****

                  if (cbValueMax > 0)
                  {
-
                      copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;

                      /* Copy the data */
--- 455,460 ----
***************
*** 482,488 ****
      }
      else
      {
-
          /*
           * for SQL_C_CHAR, it's probably ok to leave currency symbols in.
           * But to convert to numeric types, it is necessary to get rid of
--- 481,486 ----
***************
*** 632,638 ****

                  if (stmt->current_col >= 0)
                  {
-
                      /* No more data left for this column */
                      if (stmt->bindings[stmt->current_col].data_left == 0)
                          return COPY_NO_DATA_FOUND;
--- 630,635 ----
***************
*** 689,698 ****
  }


! /*    This function inserts parameters into an SQL statements.
!     It will also modify a SELECT statement for use with declare/fetch cursors.
!     This function no longer does any dynamic memory allocation!
! */
  int
  copy_statement_with_parameters(StatementClass *stmt)
  {
--- 686,696 ----
  }


! /*
!  *    This function inserts parameters into an SQL statements.
!  *    It will also modify a SELECT statement for use with declare/fetch cursors.
!  *    This function no longer does any dynamic memory allocation!
!  */
  int
  copy_statement_with_parameters(StatementClass *stmt)
  {
***************
*** 759,765 ****

      for (opos = 0; opos < oldstmtlen; opos++)
      {
-
          /* Squeeze carriage-return/linefeed pairs to linefeed only */
          if (old_statement[opos] == '\r' && opos + 1 < oldstmtlen &&
              old_statement[opos + 1] == '\n')
--- 757,762 ----
***************
*** 781,790 ****

  #ifdef MULTIBYTE
              char       *end = multibyte_strchr(begin, '}');
-
  #else
              char       *end = strchr(begin, '}');
-
  #endif

              if (!end)
--- 778,785 ----
***************
*** 806,817 ****
              }

              opos += end - begin + 1;
-
              *end = '}';
-
              continue;
          }
-
          /*
           * Can you have parameter markers inside of quotes?  I dont think
           * so. All the queries I've seen expect the driver to put quotes
--- 801,809 ----
***************
*** 827,839 ****
              new_statement[npos++] = old_statement[opos];
              continue;
          }
-
-

!         /****************************************************/
!         /* Its a '?' parameter alright                  */
!         /****************************************************/
!
          param_number++;

          if (param_number >= stmt->parameters_allocated)
--- 819,828 ----
              new_statement[npos++] = old_statement[opos];
              continue;
          }

!         /*
!          * Its a '?' parameter alright
!          */
          param_number++;

          if (param_number >= stmt->parameters_allocated)
***************
*** 882,888 ****
          param_string[0] = '\0';
          cbuf[0] = '\0';

-
          /* Convert input C type to a neutral format */
          switch (param_ctype)
          {
--- 871,876 ----
***************
*** 1089,1101 ****

                  if (stmt->parameters[param_number].data_at_exec)
                  {
-
                      lobj_oid = stmt->parameters[param_number].lobj_oid;
-
                  }
                  else
                  {
-
                      /* begin transaction if needed */
                      if (!CC_is_in_trans(stmt->hdbc))
                      {
--- 1077,1086 ----
***************
*** 1240,1254 ****
                      new_statement[npos++] = '\'';        /* Close Quote */

                  break;
-
          }
-
      }                            /* end, for */

      /* make sure new_statement is always null-terminated */
      new_statement[npos] = '\0';

-
      if (stmt->hdbc->DriverToDataSource != NULL)
      {
          int            length = strlen(new_statement);
--- 1225,1236 ----
***************
*** 1260,1266 ****
                                         NULL, 0, NULL);
      }

-
      return SQL_SUCCESS;
  }

--- 1242,1247 ----
***************
*** 1276,1282 ****
      return NULL;
  }

! /* convert_escape()
   * This function returns a pointer to static memory!
   */
  char *
--- 1257,1265 ----
      return NULL;
  }

! /*
!  * convert_escape()
!  *
   * This function returns a pointer to static memory!
   */
  char *
***************
*** 1305,1311 ****
      }
      else if (strcmp(key, "fn") == 0)
      {
-
          /*
           * Function invocation Separate off the func name, skipping
           * trailing whitespace.
--- 1288,1293 ----
***************
*** 1356,1362 ****
      }

      return escape;
-
  }


--- 1338,1343 ----
***************
*** 1381,1388 ****



! /*    This function parses a character string for date/time info and fills in SIMPLE_TIME */
! /*    It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value */
  char
  parse_datetime(char *buf, SIMPLE_TIME *st)
  {
--- 1362,1371 ----



! /*
!  *    This function parses a character string for date/time info and fills in SIMPLE_TIME
!  *    It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value
!  */
  char
  parse_datetime(char *buf, SIMPLE_TIME *st)
  {
***************
*** 1468,1476 ****
      return out;
  }

! /*    Change carriage-return/linefeed to just linefeed
!     Plus, escape any special characters.
! */
  char *
  convert_special_chars(char *si, char *dst, int used)
  {
--- 1451,1460 ----
      return out;
  }

! /*
!  *    Change carriage-return/linefeed to just linefeed
!  *    Plus, escape any special characters.
!  */
  char *
  convert_special_chars(char *si, char *dst, int used)
  {
***************
*** 1544,1550 ****

      for (i = 1; i <= 2; i++)
      {
-
          if (s[i] >= 'a' && s[i] <= 'f')
              val = s[i] - 'a' + 10;
          else if (s[i] >= 'A' && s[i] <= 'F')
--- 1528,1533 ----
***************
*** 1611,1617 ****
      int            i,
                  o = 0;

-
      for (i = 0; i < len; i++)
      {
          mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]);
--- 1594,1599 ----
***************
*** 1622,1628 ****
              strcpy(&out[o], conv_to_octal(in[i]));
              o += 5;
          }
-
      }

      mylog("convert_to_pgbinary: returning %d, out='%.*s'\n", o, o, out);
--- 1604,1609 ----
***************
*** 1679,1700 ****
      out[o++] = '\0';
  }

-

! /*    1. get oid (from 'value')
!     2. open the large object
!     3. read from the large object (handle multiple GetData)
!     4. close when read less than requested?  -OR-
!         lseek/read each time
!         handle case where application receives truncated and
!         decides not to continue reading.
!
!     CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only
!     data type currently mapped to a PG_TYPE_LO.  But, if any other types
!     are desired to map to a large object (PG_TYPE_LO), then that would
!     need to be handled here.  For example, LONGVARCHAR could possibly be
!     mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now.
! */
  int
  convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
             SDWORD cbValueMax, SDWORD *pcbValue)
--- 1660,1682 ----
      out[o++] = '\0';
  }


! /*-------
!  *    1. get oid (from 'value')
!  *    2. open the large object
!  *    3. read from the large object (handle multiple GetData)
!  *    4. close when read less than requested?  -OR-
!  *        lseek/read each time
!  *        handle case where application receives truncated and
!  *        decides not to continue reading.
!  *
!  *    CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only
!  *    data type currently mapped to a PG_TYPE_LO.  But, if any other types
!  *    are desired to map to a large object (PG_TYPE_LO), then that would
!  *    need to be handled here.  For example, LONGVARCHAR could possibly be
!  *    mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now.
!  *-------
!  */
  int
  convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
             SDWORD cbValueMax, SDWORD *pcbValue)
***************
*** 1706,1712 ****
      BindInfoClass *bindInfo = NULL;


! /*    If using SQLGetData, then current_col will be set */
      if (stmt->current_col >= 0)
      {
          bindInfo = &stmt->bindings[stmt->current_col];
--- 1688,1694 ----
      BindInfoClass *bindInfo = NULL;


!     /*    If using SQLGetData, then current_col will be set */
      if (stmt->current_col >= 0)
      {
          bindInfo = &stmt->bindings[stmt->current_col];
***************
*** 1720,1726 ****

      if (!bindInfo || bindInfo->data_left == -1)
      {
-
          /* begin transaction if needed */
          if (!CC_is_in_trans(stmt->hdbc))
          {
--- 1702,1707 ----
***************
*** 1759,1765 ****
          retval = lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_END);
          if (retval >= 0)
          {
-
              left = lo_tell(stmt->hdbc, stmt->lobj_fd);
              if (bindInfo)
                  bindInfo->data_left = left;
--- 1740,1745 ----
***************
*** 1824,1834 ****
      if (pcbValue)
          *pcbValue = left < 0 ? SQL_NO_TOTAL : left;

-
      if (bindInfo && bindInfo->data_left > 0)
          bindInfo->data_left -= retval;

-
      if (!bindInfo || bindInfo->data_left == 0)
      {
          lo_close(stmt->hdbc, stmt->lobj_fd);
--- 1804,1812 ----
***************
*** 1861,1867 ****
          stmt->lobj_fd = -1;        /* prevent further reading */
      }

-
      return result;
-
  }
--- 1839,1843 ----
Index: src/interfaces/odbc/dlg_specific.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/dlg_specific.c,v
retrieving revision 1.28
diff -c -r1.28 dlg_specific.c
*** src/interfaces/odbc/dlg_specific.c    2001/03/27 04:00:53    1.28
--- src/interfaces/odbc/dlg_specific.c    2001/03/28 16:53:14
***************
*** 1,4 ****
! /* Module:            dlg_specific.c
   *
   * Description:        This module contains any specific code for handling
   *                    dialog boxes such as driver/datasource options.  Both the
--- 1,5 ----
! /*-------
!  * Module:            dlg_specific.c
   *
   * Description:        This module contains any specific code for handling
   *                    dialog boxes such as driver/datasource options.  Both the
***************
*** 12,18 ****
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */
  /* Multibyte support    Eiji Tokuya 2001-03-15 */

--- 13,19 ----
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */
  /* Multibyte support    Eiji Tokuya 2001-03-15 */

***************
*** 54,60 ****
  void
  SetDlgStuff(HWND hdlg, ConnInfo *ci)
  {
-
      /*
       * If driver attribute NOT present, then set the datasource name and
       * description
--- 55,60 ----
***************
*** 85,91 ****
  }


-
  int            CALLBACK
  driver_optionsProc(HWND hdlg,
                     WORD wMsg,
--- 85,90 ----
***************
*** 141,147 ****
              switch (GET_WM_COMMAND_ID(wParam, lParam))
              {
                  case IDOK:
-
                      globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
                      globals.disable_optimizer = IsDlgButtonChecked(hdlg, DRV_OPTIMIZER);
                      globals.ksqo = IsDlgButtonChecked(hdlg, DRV_KSQO);
--- 140,145 ----
***************
*** 228,234 ****

                      break;
              }
-
      }

      return FALSE;
--- 226,231 ----
***************
*** 267,277 ****
              else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0)
                  CheckDlgButton(hdlg, DS_PG63, 1);
              else
! /* latest */
                  CheckDlgButton(hdlg, DS_PG64, 1);
!
!
!
              CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column));
              CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index));
              CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
--- 264,272 ----
              else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0)
                  CheckDlgButton(hdlg, DS_PG63, 1);
              else
!                 /* latest */
                  CheckDlgButton(hdlg, DS_PG64, 1);
!
              CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column));
              CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index));
              CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
***************
*** 283,289 ****
              SetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings);
              break;

-
          case WM_COMMAND:
              switch (GET_WM_COMMAND_ID(wParam, lParam))
              {
--- 278,283 ----
***************
*** 292,300 ****
                      EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN));
                      return TRUE;

-
                  case IDOK:
-
                      ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
                      mylog("IDOK: got ci = %u\n", ci);

--- 286,292 ----
***************
*** 307,313 ****
                      else if (IsDlgButtonChecked(hdlg, DS_PG63))
                          strcpy(ci->protocol, PG63);
                      else
! /* latest */
                          strcpy(ci->protocol, PG64);

                      sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES));
--- 299,305 ----
                      else if (IsDlgButtonChecked(hdlg, DS_PG63))
                          strcpy(ci->protocol, PG63);
                      else
!                         /* latest */
                          strcpy(ci->protocol, PG64);

                      sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES));
***************
*** 321,327 ****
                      /* Datasource Connection Settings */
                      GetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings, sizeof(ci->conn_settings));

-
                      /* fall through */

                  case IDCANCEL:
--- 313,318 ----
***************
*** 368,374 ****
  void
  copyAttributes(ConnInfo *ci, char *attribute, char *value)
  {
-
      if (stricmp(attribute, "DSN") == 0)
          strcpy(ci->dsn, value);

--- 359,364 ----
***************
*** 415,421 ****
      }

      mylog("copyAttributes:
DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s')\n",
ci->dsn,ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings); 
-
  }

  void
--- 405,410 ----
***************
*** 450,457 ****
      char       *DSN = ci->dsn;
      char        encoded_conn_settings[LARGE_REGISTRY_LEN];

! /*    If a driver keyword was present, then dont use a DSN and return. */
! /*    If DSN is null and no driver, then use the default datasource. */
      if (DSN[0] == '\0')
      {
          if (ci->driver[0] != '\0')
--- 439,448 ----
      char       *DSN = ci->dsn;
      char        encoded_conn_settings[LARGE_REGISTRY_LEN];

! /*
!  *    If a driver keyword was present, then dont use a DSN and return.
!  *    If DSN is null and no driver, then use the default datasource.
!  */
      if (DSN[0] == '\0')
      {
          if (ci->driver[0] != '\0')
***************
*** 514,524 ****
      if (ci->translation_option[0] == '\0' || overwrite)
          SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option,
sizeof(ci->translation_option),ODBC_INI); 

-
      /* Allow override of odbcinst.ini parameters here */
      getGlobalDefaults(DSN, ODBC_INI, TRUE);

-
      qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n",
           DSN,
           ci->server,
--- 505,513 ----
***************
*** 546,552 ****
      qlog("          translation_dll='%s',translation_option='%s'\n",
           ci->translation_dll,
           ci->translation_option);
-
  }


--- 535,540 ----
***************
*** 626,640 ****
  }


! /*    This function reads the ODBCINST.INI portion of
!     the registry and gets any driver defaults.
! */
  void
  getGlobalDefaults(char *section, char *filename, char override)
  {
      char        temp[256];

-
      /* Fetch Count is stored in driver section */
      SQLGetPrivateProfileString(section, INI_FETCH, "",
                                 temp, sizeof(temp), filename);
--- 614,628 ----
  }


! /*
!  *    This function reads the ODBCINST.INI portion of
!  *    the registry and gets any driver defaults.
!  */
  void
  getGlobalDefaults(char *section, char *filename, char override)
  {
      char        temp[256];

      /* Fetch Count is stored in driver section */
      SQLGetPrivateProfileString(section, INI_FETCH, "",
                                 temp, sizeof(temp), filename);
***************
*** 648,654 ****
      else if (!override)
          globals.fetch_max = FETCH_MAX;

-
      /* Socket Buffersize is stored in driver section */
      SQLGetPrivateProfileString(section, INI_SOCKET, "",
                                 temp, sizeof(temp), filename);
--- 636,641 ----
***************
*** 657,663 ****
      else if (!override)
          globals.socket_buffersize = SOCK_BUFFER_SIZE;

-
      /* Debug is stored in the driver section */
      SQLGetPrivateProfileString(section, INI_DEBUG, "",
                                 temp, sizeof(temp), filename);
--- 644,649 ----
***************
*** 666,672 ****
      else if (!override)
          globals.debug = DEFAULT_DEBUG;

-
      /* CommLog is stored in the driver section */
      SQLGetPrivateProfileString(section, INI_COMMLOG, "",
                                 temp, sizeof(temp), filename);
--- 652,657 ----
***************
*** 675,681 ****
      else if (!override)
          globals.commlog = DEFAULT_COMMLOG;

-
      /* Optimizer is stored in the driver section only */
      SQLGetPrivateProfileString(section, INI_OPTIMIZER, "",
                                 temp, sizeof(temp), filename);
--- 660,665 ----
***************
*** 734,741 ****
      else if (!override)
          globals.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT;

-
-
      /* UseDeclareFetch is stored in the driver section only */
      SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "",
                                 temp, sizeof(temp), filename);
--- 718,723 ----
***************
*** 744,750 ****
      else if (!override)
          globals.use_declarefetch = DEFAULT_USEDECLAREFETCH;

-
      /* Max Varchar Size */
      SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "",
                                 temp, sizeof(temp), filename);
--- 726,731 ----
***************
*** 804,810 ****
      /* Dont allow override of an override! */
      if (!override)
      {
-
          /*
           * ConnSettings is stored in the driver section and per datasource
           * for override
--- 785,790 ----
***************
*** 831,844 ****
              strcpy(globals.protocol, temp);
          else
              strcpy(globals.protocol, DEFAULT_PROTOCOL);
-
      }
  }


! /*    This function writes any global parameters (that can be manipulated)
!     to the ODBCINST.INI portion of the registry
! */
  void
  updateGlobals(void)
  {
--- 811,824 ----
              strcpy(globals.protocol, temp);
          else
              strcpy(globals.protocol, DEFAULT_PROTOCOL);
      }
  }


! /*
!  *    This function writes any global parameters (that can be manipulated)
!  *    to the ODBCINST.INI portion of the registry
!  */
  void
  updateGlobals(void)
  {
Index: src/interfaces/odbc/drvconn.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/drvconn.c,v
retrieving revision 1.22
diff -c -r1.22 drvconn.c
*** src/interfaces/odbc/drvconn.c    2001/03/27 04:00:53    1.22
--- src/interfaces/odbc/drvconn.c    2001/03/28 16:53:15
***************
*** 1,4 ****
! /* Module:            drvconn.c
   *
   * Description:        This module contains only routines related to
   *                    implementing SQLDriverConnect.
--- 1,5 ----
! /*-------
!  * Module:            drvconn.c
   *
   * Description:        This module contains only routines related to
   *                    implementing SQLDriverConnect.
***************
*** 8,14 ****
   * API functions:    SQLDriverConnect
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 9,15 ----
   * API functions:    SQLDriverConnect
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 110,118 ****
      /* Parse the connect string and fill in conninfo for this hdbc. */
      dconn_get_connect_attributes(connStrIn, ci);

!     /* If the ConnInfo in the hdbc is missing anything, */
!     /* this function will fill them in from the registry (assuming */
!     /* of course there is a DSN given -- if not, it does nothing!) */
      getDSNinfo(ci, CONN_DONT_OVERWRITE);

      /* Fill in any default parameters if they are not there. */
--- 111,121 ----
      /* Parse the connect string and fill in conninfo for this hdbc. */
      dconn_get_connect_attributes(connStrIn, ci);

!     /*
!      * If the ConnInfo in the hdbc is missing anything,
!      * this function will fill them in from the registry (assuming
!      * of course there is a DSN given -- if not, it does nothing!)
!      */
      getDSNinfo(ci, CONN_DONT_OVERWRITE);

      /* Fill in any default parameters if they are not there. */
***************
*** 147,153 ****
                  ci->port[0] == '\0' ||
                  password_required)
              {
-
                  dialog_result = dconn_DoDialog(hwnd, ci);
                  if (dialog_result != SQL_SUCCESS)
                      return dialog_result;
--- 150,155 ----
***************
*** 173,184 ****
          ci->database[0] == '\0' ||
          ci->port[0] == '\0')
      {
! /*        (password_required && ci->password[0] == '\0')) */

          return SQL_NO_DATA_FOUND;
      }

-
      /* do the actual connect */
      retval = CC_connect(conn, password_required);
      if (retval < 0)
--- 175,185 ----
          ci->database[0] == '\0' ||
          ci->port[0] == '\0')
      {
!     /*    (password_required && ci->password[0] == '\0')) */

          return SQL_NO_DATA_FOUND;
      }

      /* do the actual connect */
      retval = CC_connect(conn, password_required);
      if (retval < 0)
***************
*** 206,214 ****
          return SQL_ERROR;
      }

!     /*********************************************/
!     /* Create the Output Connection String     */
!     /*********************************************/
      result = SQL_SUCCESS;

      makeConnectString(connStrOut, ci);
--- 207,215 ----
          return SQL_ERROR;
      }

!     /*
!      * Create the Output Connection String
!      */
      result = SQL_SUCCESS;

      makeConnectString(connStrOut, ci);
***************
*** 216,222 ****

      if (szConnStrOut)
      {
-
          /*
           * Return the completed string to the caller. The correct method
           * is to only construct the connect string if a dialog was put up,
--- 217,222 ----
***************
*** 296,302 ****

              SetWindowLong(hdlg, DWL_USER, lParam);        /* Save the ConnInfo for
                                                           * the "OK" */
-
              SetDlgStuff(hdlg, ci);

              if (ci->database[0] == '\0')
--- 296,301 ----
***************
*** 309,346 ****
                  SetFocus(GetDlgItem(hdlg, IDC_USER));
              else if (ci->focus_password)
                  SetFocus(GetDlgItem(hdlg, IDC_PASSWORD));
-
-
              break;

          case WM_COMMAND:
              switch (GET_WM_COMMAND_ID(wParam, lParam))
              {
                  case IDOK:
-
                      ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);

                      GetDlgStuff(hdlg, ci);

-
                  case IDCANCEL:
                      EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
                      return TRUE;

                  case IDC_DRIVER:
-
                      DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
                                  hdlg, driver_optionsProc, (LPARAM) NULL);
-
-
                      break;

                  case IDC_DATASOURCE:
-
                      ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
                      DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
                                     hdlg, ds_optionsProc, (LPARAM) ci);
-
                      break;
              }
      }
--- 308,336 ----
***************
*** 392,398 ****
          copyAttributes(ci, attribute, value);

      }
-

      free(our_connect_string);
  }
--- 382,387 ----
Index: src/interfaces/odbc/environ.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/environ.c,v
retrieving revision 1.24
diff -c -r1.24 environ.c
*** src/interfaces/odbc/environ.c    2001/03/27 04:00:53    1.24
--- src/interfaces/odbc/environ.c    2001/03/28 16:53:15
***************
*** 1,4 ****
! /* Module:            environ.c
   *
   * Description:        This module contains routines related to
   *                    the environment, such as storing connection handles,
--- 1,5 ----
! /*-------
!  * Module:            environ.c
   *
   * Description:        This module contains routines related to
   *                    the environment, such as storing connection handles,
***************
*** 9,15 ****
   * API functions:    SQLAllocEnv, SQLFreeEnv, SQLError
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #include "environ.h"
--- 10,16 ----
   * API functions:    SQLAllocEnv, SQLFreeEnv, SQLError
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #include "environ.h"
***************
*** 208,231 ****
                      case STMT_INVALID_CURSOR_POSITION:
                          strcpy(szSqlState, "S1109");
                          break;
-
                      case STMT_VALUE_OUT_OF_RANGE:
                          strcpy(szSqlState, "22003");
                          break;
-
                      case STMT_OPERATION_INVALID:
                          strcpy(szSqlState, "S1011");
                          break;
-
                      case STMT_EXEC_ERROR:
                      default:
                          strcpy(szSqlState, "S1000");
                          /* also a general error */
                          break;
                  }
-
              mylog("       szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg);
-
          }
          else
          {
--- 209,227 ----
***************
*** 237,246 ****
                  szErrorMsg[0] = '\0';

              mylog("       returning NO_DATA_FOUND\n");
              return SQL_NO_DATA_FOUND;
          }
-         return SQL_SUCCESS;

      }
      else if (SQL_NULL_HDBC != hdbc)
      {
--- 233,243 ----
                  szErrorMsg[0] = '\0';

              mylog("       returning NO_DATA_FOUND\n");
+
              return SQL_NO_DATA_FOUND;
          }

+         return SQL_SUCCESS;
      }
      else if (SQL_NULL_HDBC != hdbc)
      {
***************
*** 310,316 ****
                          break;
                      case CONN_TRANSACT_IN_PROGRES:
                          strcpy(szSqlState, "S1010");
-
                          /*
                           * when the user tries to switch commit mode in a
                           * transaction
--- 307,312 ----
***************
*** 324,341 ****
                      case STMT_NOT_IMPLEMENTED_ERROR:
                          strcpy(szSqlState, "S1C00");
                          break;
-
                      case CONN_VALUE_OUT_OF_RANGE:
                      case STMT_VALUE_OUT_OF_RANGE:
                          strcpy(szSqlState, "22003");
                          break;
-
                      default:
                          strcpy(szSqlState, "S1000");
                          /* general error */
                          break;
                  }
-
          }
          else
          {
--- 320,334 ----
***************
*** 349,356 ****

              return SQL_NO_DATA_FOUND;
          }
-         return SQL_SUCCESS;

      }
      else if (SQL_NULL_HENV != henv)
      {
--- 342,349 ----

              return SQL_NO_DATA_FOUND;
          }

+         return SQL_SUCCESS;
      }
      else if (SQL_NULL_HENV != henv)
      {
***************
*** 419,433 ****
  }


- /*********************************************************************/
  /*
   * EnvironmentClass implementation
   */
!
!
!
! EnvironmentClass
!            *
  EN_Constructor(void)
  {
      EnvironmentClass *rv;
--- 412,421 ----
  }


  /*
   * EnvironmentClass implementation
   */
! EnvironmentClass *
  EN_Constructor(void)
  {
      EnvironmentClass *rv;
***************
*** 451,458 ****

      mylog("in EN_Destructor, self=%u\n", self);

!     /* the error messages are static strings distributed throughout */
!     /* the source--they should not be freed */

      /* Free any connections belonging to this environment */
      for (lf = 0; lf < MAX_CONNECTIONS; lf++)
--- 439,448 ----

      mylog("in EN_Destructor, self=%u\n", self);

!     /*
!      * the error messages are static strings distributed throughout
!      * the source--they should not be freed
!      */

      /* Free any connections belonging to this environment */
      for (lf = 0; lf < MAX_CONNECTIONS; lf++)
Index: src/interfaces/odbc/execute.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/execute.c,v
retrieving revision 1.25
diff -c -r1.25 execute.c
*** src/interfaces/odbc/execute.c    2001/03/27 04:00:53    1.25
--- src/interfaces/odbc/execute.c    2001/03/28 16:53:15
***************
*** 1,4 ****
! /* Module:            execute.c
   *
   * Description:        This module contains routines related to
   *                    preparing and executing an SQL statement.
--- 1,5 ----
! /*-------
!  * Module:            execute.c
   *
   * Description:        This module contains routines related to
   *                    preparing and executing an SQL statement.
***************
*** 9,15 ****
   *                    SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 10,16 ----
   *                    SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 125,138 ****
      }

      return SQL_SUCCESS;
-
-
  }

- /*        -        -        -        -        -        -        -        -        - */
-
  /*        Performs the equivalent of SQLPrepare, followed by SQLExecute. */
-
  RETCODE SQL_API
  SQLExecDirect(
                HSTMT hstmt,
--- 126,134 ----
***************
*** 154,161 ****
      if (stmt->statement)
          free(stmt->statement);

!     /* keep a copy of the un-parametrized statement, in case */
!     /* they try to execute this statement again */
      stmt->statement = make_string(szSqlStr, cbSqlStr, NULL);
      if (!stmt->statement)
      {
--- 150,159 ----
      if (stmt->statement)
          free(stmt->statement);

!     /*
!      * keep a copy of the un-parametrized statement, in case
!      * they try to execute this statement again
!      */
      stmt->statement = make_string(szSqlStr, cbSqlStr, NULL);
      if (!stmt->statement)
      {
***************
*** 169,177 ****

      stmt->prepare = FALSE;

!     /* If an SQLPrepare was performed prior to this, but was left in  */
!     /* the premature state because an error occurred prior to SQLExecute */
!     /* then set the statement to finished so it can be recycled. */
      if (stmt->status == STMT_PREMATURE)
          stmt->status = STMT_FINISHED;

--- 167,177 ----

      stmt->prepare = FALSE;

!     /*
!      * If an SQLPrepare was performed prior to this, but was left in
!      * the premature state because an error occurred prior to SQLExecute
!      * then set the statement to finished so it can be recycled.
!      */
      if (stmt->status == STMT_PREMATURE)
          stmt->status = STMT_FINISHED;

***************
*** 194,200 ****
      return result;
  }

! /*        Execute a prepared SQL statement */
  RETCODE SQL_API
  SQLExecute(
             HSTMT hstmt)
--- 194,200 ----
      return result;
  }

! /*    Execute a prepared SQL statement */
  RETCODE SQL_API
  SQLExecute(
             HSTMT hstmt)
***************
*** 205,211 ****
      int            i,
                  retval;

-
      mylog("%s: entering...\n", func);

      if (!stmt)
--- 205,210 ----
***************
*** 274,280 ****
      if ((stmt->prepare && stmt->status != STMT_READY) ||
          (stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
      {
-
          stmt->errornumber = STMT_STATUS_ERROR;
          stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
          SC_log_error(func, "", stmt);
--- 273,278 ----
***************
*** 282,288 ****
          return SQL_ERROR;
      }

-
      /*
       * The bound parameters could have possibly changed since the last
       * execute of this statement?  Therefore check for params and re-copy.
--- 280,285 ----
***************
*** 319,333 ****

      mylog("   stmt_with_params = '%s'\n", stmt->stmt_with_params);

-
      return SC_execute(stmt);
-
  }


-
-
- /*        -        -        -        -        -        -        -        -        - */
  RETCODE SQL_API
  SQLTransact(
              HENV henv,
--- 316,325 ----
***************
*** 363,369 ****
              if (conn && conn->henv == henv)
                  if (SQLTransact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
                      return SQL_ERROR;
-
          }
          return SQL_SUCCESS;
      }
--- 355,360 ----
***************
*** 371,385 ****
      conn = (ConnectionClass *) hdbc;

      if (fType == SQL_COMMIT)
-     {
          stmt_string = "COMMIT";
-
-     }
      else if (fType == SQL_ROLLBACK)
-     {
          stmt_string = "ROLLBACK";
-
-     }
      else
      {
          conn->errornumber = CONN_INVALID_ARGUMENT_NO;
--- 362,370 ----
***************
*** 391,397 ****
      /* If manual commit and in transaction, then proceed. */
      if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
      {
-
          mylog("SQLTransact: sending on conn %d '%s'\n", conn, stmt_string);

          res = CC_send_query(conn, stmt_string, NULL);
--- 376,381 ----
***************
*** 416,422 ****
      return SQL_SUCCESS;
  }

- /*        -        -        -        -        -        -        -        -        - */

  RETCODE SQL_API
  SQLCancel(
--- 400,405 ----
***************
*** 447,454 ****
       */
      if (stmt->data_at_exec < 0)
      {
-
-
          /*
           * MAJOR HACK for Windows to reset the driver manager's cursor
           * state: Because of what seems like a bug in the Odbc driver
--- 430,435 ----
***************
*** 490,503 ****
      stmt->put_data = FALSE;

      return SQL_SUCCESS;
-
  }

- /*        -        -        -        -        -        -        -        -        - */

! /*        Returns the SQL string as modified by the driver. */
! /*        Currently, just copy the input string without modification */
! /*        observing buffer limits and truncation. */
  RETCODE SQL_API
  SQLNativeSql(
               HDBC hdbc,
--- 471,484 ----
      stmt->put_data = FALSE;

      return SQL_SUCCESS;
  }


! /*
!  *    Returns the SQL string as modified by the driver.
!  *    Currently, just copy the input string without modification
!  *    observing buffer limits and truncation.
!  */
  RETCODE SQL_API
  SQLNativeSql(
               HDBC hdbc,
***************
*** 546,557 ****

      return result;
  }
-
- /*        -        -        -        -        -        -        -        -        - */

! /*        Supplies parameter data at execution time.        Used in conjuction with */
! /*        SQLPutData. */
!
  RETCODE SQL_API
  SQLParamData(
               HSTMT hstmt,
--- 527,537 ----

      return result;
  }

! /*
!  *    Supplies parameter data at execution time.
!  *    Used in conjuction with SQLPutData.
!  */
  RETCODE SQL_API
  SQLParamData(
               HSTMT hstmt,
***************
*** 619,629 ****

              CC_set_no_trans(stmt->hdbc);
          }
-
          stmt->lobj_fd = -1;
      }

-
      /* Done, now copy the params and then execute the statement */
      if (stmt->data_at_exec == 0)
      {
--- 599,607 ----
***************
*** 657,668 ****

      return SQL_NEED_DATA;
  }
-
- /*        -        -        -        -        -        -        -        -        - */

! /*        Supplies parameter data at execution time.        Used in conjunction with */
! /*        SQLParamData. */
!
  RETCODE SQL_API
  SQLPutData(
             HSTMT hstmt,
--- 635,645 ----

      return SQL_NEED_DATA;
  }

! /*
!  *    Supplies parameter data at execution time.
!  *    Used in conjunction with SQLParamData.
!  */
  RETCODE SQL_API
  SQLPutData(
             HSTMT hstmt,
***************
*** 684,690 ****
          return SQL_INVALID_HANDLE;
      }

-
      if (stmt->current_exec_param < 0)
      {
          stmt->errornumber = STMT_SEQUENCE_ERROR;
--- 661,666 ----
***************
*** 697,703 ****

      if (!stmt->put_data)
      {                            /* first call */
-
          mylog("SQLPutData: (1) cbValue = %d\n", cbValue);

          stmt->put_data = TRUE;
--- 673,678 ----
***************
*** 716,726 ****
          if (cbValue == SQL_NULL_DATA)
              return SQL_SUCCESS;

-
          /* Handle Long Var Binary with Large Objects */
          if (current_param->SQLType == SQL_LONGVARBINARY)
          {
-
              /* begin transaction if needed */
              if (!CC_is_in_trans(stmt->hdbc))
              {
--- 691,699 ----
***************
*** 758,765 ****
                  return SQL_ERROR;
              }

!             /* major hack -- to allow convert to see somethings there */
!             /* have to modify convert to handle this better */
              current_param->EXEC_buffer = (char *) ¤t_param->lobj_oid;

              /* store the fd */
--- 731,740 ----
                  return SQL_ERROR;
              }

!             /*
!              * major hack -- to allow convert to see somethings there
!              * have to modify convert to handle this better
!              */
              current_param->EXEC_buffer = (char *) ¤t_param->lobj_oid;

              /* store the fd */
***************
*** 774,785 ****

              retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
              mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval);
-
          }
          else
!         {                        /* for handling text fields and small
!                                  * binaries */
!
              if (cbValue == SQL_NTS)
              {
                  current_param->EXEC_buffer = strdup(rgbValue);
--- 749,758 ----

              retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
              mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval);
          }
          else
!         {
!             /* for handling text fields and small binaries */
              if (cbValue == SQL_NTS)
              {
                  current_param->EXEC_buffer = strdup(rgbValue);
***************
*** 806,830 ****
              }
          }
      }
-
      else
!     {                            /* calling SQLPutData more than once */
!
          mylog("SQLPutData: (>1) cbValue = %d\n", cbValue);

          if (current_param->SQLType == SQL_LONGVARBINARY)
          {
-
              /* the large object fd is in EXEC_buffer */
              retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
              mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval);

              *current_param->EXEC_used += cbValue;
-
          }
          else
          {
-
              buffer = current_param->EXEC_buffer;

              if (cbValue == SQL_NTS)
--- 779,799 ----
              }
          }
      }
      else
!     {
!         /* calling SQLPutData more than once */
          mylog("SQLPutData: (>1) cbValue = %d\n", cbValue);

          if (current_param->SQLType == SQL_LONGVARBINARY)
          {
              /* the large object fd is in EXEC_buffer */
              retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
              mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval);

              *current_param->EXEC_used += cbValue;
          }
          else
          {
              buffer = current_param->EXEC_buffer;

              if (cbValue == SQL_NTS)
***************
*** 845,855 ****

                  /* reassign buffer incase realloc moved it */
                  current_param->EXEC_buffer = buffer;
-
              }
              else if (cbValue > 0)
              {
-
                  old_pos = *current_param->EXEC_used;

                  *current_param->EXEC_used += cbValue;
--- 814,822 ----
***************
*** 871,887 ****

                  /* reassign buffer incase realloc moved it */
                  current_param->EXEC_buffer = buffer;
-
              }
              else
              {
                  SC_log_error(func, "bad cbValue", stmt);
                  return SQL_ERROR;
              }
-
          }
      }
-

      return SQL_SUCCESS;
  }
--- 838,851 ----
Index: src/interfaces/odbc/gpps.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/gpps.c,v
retrieving revision 1.17
diff -c -r1.17 gpps.c
*** src/interfaces/odbc/gpps.c    2001/03/27 04:00:53    1.17
--- src/interfaces/odbc/gpps.c    2001/03/28 16:53:15
***************
*** 1,4 ****
! /* GetPrivateProfileString()
   *
   * approximate implementation of
   * Windows NT System Services version of GetPrivateProfileString()
--- 1,5 ----
! /*-------
!  * GetPrivateProfileString()
   *
   * approximate implementation of
   * Windows NT System Services version of GetPrivateProfileString()
***************
*** 15,20 ****
--- 16,22 ----
   * are allowed (that is an anachronism anyway)
   * Added code to search for ODBC_INI file in users home directory on
   * Unix
+  *-------
   */

  #ifndef WIN32
***************
*** 46,52 ****

  DWORD
  GetPrivateProfileString(char *theSection,        /* section name */
!                         char *theKey,    /* search key name */
                          char *theDefault,        /* default value if not
                                                   * found */
                          char *theReturnBuffer,    /* return value stored
--- 48,54 ----

  DWORD
  GetPrivateProfileString(char *theSection,        /* section name */
!                         char *theKey,            /* search key name */
                          char *theDefault,        /* default value if not
                                                   * found */
                          char *theReturnBuffer,    /* return value stored
***************
*** 110,116 ****
          aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
      }

-
      aLength = (theDefault == NULL) ? 0 : strlen(theDefault);

      if (theReturnBufferLength == 0 || theReturnBuffer == NULL)
--- 112,117 ----
***************
*** 123,129 ****
      if (aFile == NULL)
      {
          /* no ini file specified, return the default */
-
          ++aLength;                /* room for NULL char */
          aLength = theReturnBufferLength < aLength ?
              theReturnBufferLength : aLength;
--- 124,129 ----
***************
*** 132,138 ****
          return aLength - 1;
      }

-
      while (fgets(aLine, sizeof(aLine), aFile) != NULL)
      {
          aLineLength = strlen(aLine);
--- 132,137 ----
***************
*** 147,153 ****
                  break;

              case '[':            /* section marker */
-
                  if ((aString = strchr(aLine, ']')))
                  {
                      aStart = aLine + 1;
--- 146,151 ----
***************
*** 159,188 ****
                      *(aString + 1) = '\0';

                      /* accept as matched if NULL key or exact match */
-
                      if (!theSection || !strcmp(aStart, theSection))
                          aSectionFound = TRUE;
                      else
                          aSectionFound = FALSE;
                  }
-
                  break;

              default:

                  /* try to match value keys if in proper section */
-
                  if (aSectionFound)
                  {
                      /* try to match requested key */
-
                      if ((aString = aValue = strchr(aLine, '=')))
                      {
                          *aValue = '\0';
                          ++aValue;

                          /* strip leading blanks in value field */
-
                          while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
                              *aValue++ = '\0';
                          if (aValue >= aLine + sizeof(aLine))
--- 157,181 ----
***************
*** 196,202 ****
                          aStart++;

                      /* strip trailing blanks from key */
-
                      if (aString)
                      {
                          while (--aString >= aStart && *aString == ' ')
--- 189,194 ----
***************
*** 204,219 ****
                      }

                      /* see if key is matched */
-
                      if (theKey == NULL || !strcmp(theKey, aStart))
                      {
                          /* matched -- first, terminate value part */
-
                          aKeyFound = TRUE;
                          aLength = strlen(aValue);

                          /* remove trailing blanks from aValue if any */
-
                          aString = aValue + aLength - 1;

                          while (--aString > aValue && *aString == ' ')
--- 196,208 ----
***************
*** 223,229 ****
                          }

                          /* unquote value if quoted */
-
                          if (aLength >= 2 && aValue[0] == '"' &&
                              aValue[aLength - 1] == '"')
                          {
--- 212,217 ----
***************
*** 236,242 ****
                          else
                          {
                              /* single quotes allowed also... */
-
                              if (aLength >= 2 && aValue[0] == '\'' &&
                                  aValue[aLength - 1] == '\'')
                              {
--- 224,229 ----
***************
*** 247,259 ****
                          }

                          /* compute maximum length copyable */
-
                          aLineLength = (aLength <
                          theReturnBufferLength - aReturnLength) ? aLength :
                              theReturnBufferLength - aReturnLength;

                          /* do the copy to return buffer */
-
                          if (aLineLength)
                          {
                              strncpy(&theReturnBuffer[aReturnLength],
--- 234,244 ----
***************
*** 270,280 ****
                              fclose(aFile);
                              aFile = NULL;
                          }
-
                          return aReturnLength > 0 ? aReturnLength - 1 : 0;
                      }
                  }
-
                  break;
          }
      }
--- 255,263 ----
***************
*** 283,289 ****
          fclose(aFile);

      if (!aKeyFound)
!     {                            /* key wasn't found return default */
          ++aLength;                /* room for NULL char */
          aLength = theReturnBufferLength < aLength ?
              theReturnBufferLength : aLength;
--- 266,273 ----
          fclose(aFile);

      if (!aKeyFound)
!     {
!         /* key wasn't found return default */
          ++aLength;                /* room for NULL char */
          aLength = theReturnBufferLength < aLength ?
              theReturnBufferLength : aLength;
***************
*** 296,302 ****

  DWORD
  WritePrivateProfileString(char *theSection,        /* section name */
!                           char *theKey, /* write key name */
                            char *theBuffer,        /* input buffer */
                            char *theIniFileName) /* pathname of ini file to
                                                   * write */
--- 280,286 ----

  DWORD
  WritePrivateProfileString(char *theSection,        /* section name */
!                           char *theKey,         /* write key name */
                            char *theBuffer,        /* input buffer */
                            char *theIniFileName) /* pathname of ini file to
                                                   * write */
***************
*** 305,317 ****
  }

  #if 0
! /* Ok. What the hell's the default behaviour for a null input buffer, and null
   * section name. For now if either are null I ignore the request, until
   * I find out different.
   */
  DWORD
  WritePrivateProfileString(char *theSection,        /* section name */
!                           char *theKey, /* write key name */
                            char *theBuffer,        /* input buffer */
                            char *theIniFileName) /* pathname of ini file to
                                                   * write */
--- 289,302 ----
  }

  #if 0
! /*
!  * Ok. What the hell's the default behaviour for a null input buffer, and null
   * section name. For now if either are null I ignore the request, until
   * I find out different.
   */
  DWORD
  WritePrivateProfileString(char *theSection,        /* section name */
!                           char *theKey,         /* write key name */
                            char *theBuffer,        /* input buffer */
                            char *theIniFileName) /* pathname of ini file to
                                                   * write */
***************
*** 353,363 ****
      if (ptr == NULL || *ptr == '\0')
          ptr = "/home";

!     /* This doesn't make it so we find an ini file but allows normal */
!     /* processing to continue further on down. The likelihood is that */
!     /* the file won't be found and thus the default value will be */
!     /* returned. */
!     /* */
      if (MAXPGPATH - 1 < strlen(ptr) + j)
      {
          if (MAXPGPATH - 1 < strlen(ptr))
--- 338,349 ----
      if (ptr == NULL || *ptr == '\0')
          ptr = "/home";

!     /*
!      * This doesn't make it so we find an ini file but allows normal
!      * processing to continue further on down. The likelihood is that
!      * the file won't be found and thus the default value will be
!      * returned.
!      */
      if (MAXPGPATH - 1 < strlen(ptr) + j)
      {
          if (MAXPGPATH - 1 < strlen(ptr))
***************
*** 368,376 ****

      sprintf(buf, "%s/%s", ptr, theIniFileName);

!     /* This code makes it so that a file in the users home dir */
!     /* overrides a the "default" file as passed in */
!     /* */
      aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL);
      if (!aFile)
      {
--- 354,363 ----

      sprintf(buf, "%s/%s", ptr, theIniFileName);

!     /*
!      * This code makes it so that a file in the users home dir
!      * overrides a the "default" file as passed in
!      */
      aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL);
      if (!aFile)
      {
***************
*** 380,392 ****
              return 0;
      }

-
      aLength = strlen(theBuffer);

!     /* We have to search for theKey, because if it already */
!     /* exists we have to overwrite it. If it doesn't exist */
!     /* we just write a new line to the file. */
!     /* */
      while (fgets(aLine, sizeof(aLine), aFile) != NULL)
      {
          aLineLength = strlen(aLine);
--- 367,379 ----
              return 0;
      }

      aLength = strlen(theBuffer);

!     /*
!      * We have to search for theKey, because if it already
!      * exists we have to overwrite it. If it doesn't exist
!      * we just write a new line to the file.
!      */
      while (fgets(aLine, sizeof(aLine), aFile) != NULL)
      {
          aLineLength = strlen(aLine);
***************
*** 401,407 ****
                  break;

              case '[':            /* section marker */
-
                  if ((aString = strchr(aLine, ']')))
                  {
                      *aString = '\0';
--- 388,393 ----
***************
*** 411,423 ****
                      if (!strcmp(aLine + 1, theSection))
                          aSectionFound = TRUE;
                  }
-
                  break;

              default:
-
                  /* try to match value keys if in proper section */
-
                  if (aSectionFound)
                  {
                      /* try to match requested key */
--- 397,406 ----
***************
*** 428,434 ****
                          ++aValue;

                          /* strip leading blanks in value field */
-
                          while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
                              *aValue++ = '\0';
                          if (aValue >= aLine + sizeof(aLine))
--- 411,416 ----
***************
*** 438,444 ****
                          aValue = "";

                      /* strip trailing blanks from key */
-
                      if (aString)
                      {
                          while (--aString >= aLine && *aString == ' ')
--- 420,425 ----
***************
*** 446,452 ****
                      }

                      /* see if key is matched */
-
                      if (!strcmp(theKey, aLine))
                      {
                          keyFound = TRUE;
--- 427,432 ----
***************
*** 460,466 ****
                      }
                  }
          }
-
          break;
      }
  }
--- 440,445 ----
Index: src/interfaces/odbc/info.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/info.c,v
retrieving revision 1.44
diff -c -r1.44 info.c
*** src/interfaces/odbc/info.c    2001/03/27 04:00:53    1.44
--- src/interfaces/odbc/info.c    2001/03/28 16:53:17
***************
*** 1,4 ****
! /* Module:            info.c
   *
   * Description:        This module contains routines related to
   *                    ODBC informational functions.
--- 1,5 ----
! /*--------
!  * Module:            info.c
   *
   * Description:        This module contains routines related to
   *                    ODBC informational functions.
***************
*** 12,18 ****
   *                    SQLTablePrivileges(NI), SQLColumnPrivileges(NI)
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 13,19 ----
   *                    SQLTablePrivileges(NI), SQLColumnPrivileges(NI)
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *--------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 56,63 ****
  extern GLOBAL_VALUES globals;


- /*        -        -        -        -        -        -        -        -        - */
-
  RETCODE SQL_API
  SQLGetInfo(
             HDBC hdbc,
--- 57,62 ----
***************
*** 154,160 ****
              break;

          case SQL_CORRELATION_NAME:        /* ODBC 1.0 */
-
              /*
               * Saying no correlation name makes Query not work right.
               * value = SQL_CN_NONE;
--- 153,158 ----
***************
*** 182,192 ****
              break;

          case SQL_DATABASE_NAME:/* Support for old ODBC 1.0 Apps */
-
              /*
               * Returning the database name causes problems in MS Query. It
!              * generates query like: "SELECT DISTINCT a FROM byronncrap3
!              * crap3"
               *
               * p = CC_get_database(conn);
               */
--- 180,189 ----
              break;

          case SQL_DATABASE_NAME:/* Support for old ODBC 1.0 Apps */
              /*
               * Returning the database name causes problems in MS Query. It
!              * generates query like: "SELECT DISTINCT a FROM byronnbad3
!              * bad3"
               *
               * p = CC_get_database(conn);
               */
***************
*** 198,204 ****
              break;

          case SQL_DBMS_VER:        /* ODBC 1.0 */
-
              /*
               * The ODBC spec wants ##.##.#### ...whatever... so prepend
               * the driver
--- 195,200 ----
***************
*** 256,262 ****
              break;

          case SQL_IDENTIFIER_CASE:        /* ODBC 1.0 */
-
              /*
               * are identifiers case-sensitive (yes, but only when quoted.
               * If not quoted, they default to lowercase)
--- 252,257 ----
***************
*** 275,281 ****
              break;

          case SQL_LIKE_ESCAPE_CLAUSE:    /* ODBC 2.0 */
-
              /*
               * is there a character that escapes '%' and '_' in a LIKE
               * clause? not as far as I can tell
--- 270,275 ----
***************
*** 356,373 ****
          case SQL_MAX_ROW_SIZE:    /* ODBC 2.0 */
              len = 4;
              if (PG_VERSION_GE(conn, 7.1))
!             {                    /* Large Rowa in 7.1+ */
                  value = MAX_ROW_SIZE;
              }
              else
!             {                    /* Without the Toaster we're limited to
!                                  * the blocksize */
                  value = BLCKSZ;
              }
              break;

          case SQL_MAX_ROW_SIZE_INCLUDES_LONG:    /* ODBC 2.0 */
-
              /*
               * does the preceding value include LONGVARCHAR and
               * LONGVARBINARY fields?   Well, it does include longvarchar,
--- 350,367 ----
          case SQL_MAX_ROW_SIZE:    /* ODBC 2.0 */
              len = 4;
              if (PG_VERSION_GE(conn, 7.1))
!             {
!                 /* Large Rowa in 7.1+ */
                  value = MAX_ROW_SIZE;
              }
              else
!             {
!                 /* Without the Toaster we're limited to the blocksize */
                  value = BLCKSZ;
              }
              break;

          case SQL_MAX_ROW_SIZE_INCLUDES_LONG:    /* ODBC 2.0 */
              /*
               * does the preceding value include LONGVARCHAR and
               * LONGVARBINARY fields?   Well, it does include longvarchar,
***************
*** 379,393 ****
          case SQL_MAX_STATEMENT_LEN:        /* ODBC 2.0 */
              /* maybe this should be 0? */
              len = 4;
              if (PG_VERSION_GE(conn, 7.0))
-             {                    /* Long Queries in 7.0+ */
                  value = MAX_STATEMENT_LEN;
!             }
!             else if (PG_VERSION_GE(conn, 6.5))    /* Prior to 7.0 we used
!                                                  * 2*BLCKSZ */
                  value = (2 * BLCKSZ);
              else
! /* Prior to 6.5 we used BLCKSZ */
                  value = BLCKSZ;

              break;
--- 373,386 ----
          case SQL_MAX_STATEMENT_LEN:        /* ODBC 2.0 */
              /* maybe this should be 0? */
              len = 4;
+             /* Long Queries in 7.0+ */
              if (PG_VERSION_GE(conn, 7.0))
                  value = MAX_STATEMENT_LEN;
!             /* Prior to 7.0 we used 2*BLCKSZ */
!             else if (PG_VERSION_GE(conn, 6.5))
                  value = (2 * BLCKSZ);
              else
!                 /* Prior to 6.5 we used BLCKSZ */
                  value = BLCKSZ;

              break;
***************
*** 417,425 ****
              break;

          case SQL_NEED_LONG_DATA_LEN:    /* ODBC 2.0 */
-
              /*
!              * Dont need the length, SQLPutData can handle any size and
               * multiple calls
               */
              p = "N";
--- 410,417 ----
              break;

          case SQL_NEED_LONG_DATA_LEN:    /* ODBC 2.0 */
              /*
!              * Don't need the length, SQLPutData can handle any size and
               * multiple calls
               */
              p = "N";
***************
*** 463,469 ****
          case SQL_OJ_CAPABILITIES:        /* ODBC 2.01 */
              len = 4;
              if (PG_VERSION_GE(conn, 7.1))
!             {                    /* OJs in 7.1+ */
                  value = (SQL_OJ_LEFT |
                           SQL_OJ_RIGHT |
                           SQL_OJ_FULL |
--- 455,462 ----
          case SQL_OJ_CAPABILITIES:        /* ODBC 2.01 */
              len = 4;
              if (PG_VERSION_GE(conn, 7.1))
!             {
!                 /* OJs in 7.1+ */
                  value = (SQL_OJ_LEFT |
                           SQL_OJ_RIGHT |
                           SQL_OJ_FULL |
***************
*** 473,481 ****
                           SQL_OJ_ALL_COMPARISON_OPS);
              }
              else
!             {                    /* OJs not in <7.1 */
                  value = 0;
-             }
              break;

          case SQL_ORDER_BY_COLUMNS_IN_SELECT:    /* ODBC 2.0 */
--- 466,473 ----
                           SQL_OJ_ALL_COMPARISON_OPS);
              }
              else
!                 /* OJs not in <7.1 */
                  value = 0;
              break;

          case SQL_ORDER_BY_COLUMNS_IN_SELECT:    /* ODBC 2.0 */
***************
*** 484,496 ****

          case SQL_OUTER_JOINS:    /* ODBC 1.0 */
              if (PG_VERSION_GE(conn, 7.1))
!             {                    /* OJs in 7.1+ */
                  p = "Y";
-             }
              else
!             {                    /* OJs not in <7.1 */
                  p = "N";
-             }
              break;

          case SQL_OWNER_TERM:    /* ODBC 1.0 */
--- 476,486 ----

          case SQL_OUTER_JOINS:    /* ODBC 1.0 */
              if (PG_VERSION_GE(conn, 7.1))
!                 /* OJs in 7.1+ */
                  p = "Y";
              else
!                 /* OJs not in <7.1 */
                  p = "N";
              break;

          case SQL_OWNER_TERM:    /* ODBC 1.0 */
***************
*** 547,553 ****
              break;

          case SQL_ROW_UPDATES:    /* ODBC 1.0 */
-
              /*
               * Driver doesn't support keyset-driven or mixed cursors, so
               * not much point in saying row updates are supported
--- 537,542 ----
***************
*** 635,641 ****
              break;

          case SQL_TXN_CAPABLE:    /* ODBC 1.0 */
-
              /*
               * Postgres can deal with create or drop table statements in a
               * transaction
--- 624,629 ----
***************
*** 677,683 ****
       * what length would be required if a real buffer had been passed in.
       */
      if (p)
!     {                            /* char/binary data */
          len = strlen(p);

          if (rgbInfoValue)
--- 665,672 ----
       * what length would be required if a real buffer had been passed in.
       */
      if (p)
!     {
!         /* char/binary data */
          len = strlen(p);

          if (rgbInfoValue)
***************
*** 692,704 ****
              }
          }
      }
-
      else
!     {                            /* numeric data */
!
          if (rgbInfoValue)
          {
-
              if (len == 2)
                  *((WORD *) rgbInfoValue) = (WORD) value;
              else if (len == 4)
--- 681,691 ----
              }
          }
      }
      else
!     {
!         /* numeric data */
          if (rgbInfoValue)
          {
              if (len == 2)
                  *((WORD *) rgbInfoValue) = (WORD) value;
              else if (len == 4)
***************
*** 712,719 ****
      return result;
  }

- /*        -        -        -        -        -        -        -        -        - */
-

  RETCODE SQL_API
  SQLGetTypeInfo(
--- 699,704 ----
***************
*** 725,731 ****
      TupleNode  *row;
      int            i;

! /* Int4 type; */
      Int4        pgType;
      Int2        sqlType;

--- 710,716 ----
      TupleNode  *row;
      int            i;

!     /* Int4 type; */
      Int4        pgType;
      Int2        sqlType;

***************
*** 737,743 ****
          return SQL_INVALID_HANDLE;
      }

-
      stmt->manual_result = TRUE;
      stmt->result = QR_Constructor();
      if (!stmt->result)
--- 722,727 ----
***************
*** 801,807 ****
          }
      }

-
      stmt->status = STMT_FINISHED;
      stmt->currTuple = -1;
      stmt->rowset_start = -1;
--- 785,790 ----
***************
*** 810,816 ****
      return SQL_SUCCESS;
  }

- /*        -        -        -        -        -        -        -        -        - */

  RETCODE SQL_API
  SQLGetFunctions(
--- 793,798 ----
***************
*** 824,830 ****

      if (fFunction == SQL_API_ALL_FUNCTIONS)
      {
-
          if (globals.lie)
          {
              int            i;
--- 806,811 ----
***************
*** 910,922 ****
      }
      else
      {
-
          if (globals.lie)
              *pfExists = TRUE;
-
          else
          {
-
              switch (fFunction)
              {
                  case SQL_API_SQLALLOCCONNECT:
--- 891,900 ----
***************
*** 1094,1105 ****
              }
          }
      }
-
      return SQL_SUCCESS;
  }


-
  RETCODE SQL_API
  SQLTables(
            HSTMT hstmt,
--- 1072,1081 ----
***************
*** 1160,1173 ****
          return SQL_ERROR;
      }
      tbl_stmt = (StatementClass *) htbl_stmt;
-
-     /* ********************************************************************** */
-     /* Create the query to find out the tables */
-     /* ********************************************************************** */

      if (PG_VERSION_GE(conn, 7.1))
!     {                            /* view is represented by its relkind
!                                  * since 7.1 */
          strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user");
          strcat(tables_query, " where relkind in ('r', 'v')");
      }
--- 1136,1148 ----
          return SQL_ERROR;
      }
      tbl_stmt = (StatementClass *) htbl_stmt;

+     /*
+      * Create the query to find out the tables
+      */
      if (PG_VERSION_GE(conn, 7.1))
!     {
!         /* view is represented by its relkind since 7.1 */
          strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user");
          strcat(tables_query, " where relkind in ('r', 'v')");
      }
***************
*** 1180,1194 ****
      my_strcat(tables_query, " and usename like '%.*s'", szTableOwner, cbTableOwner);
      my_strcat(tables_query, " and relname like '%.*s'", szTableName, cbTableName);

-
      /* Parse the extra systable prefix    */
      strcpy(prefixes, globals.extra_systable_prefixes);
      i = 0;
      prefix[i] = strtok(prefixes, ";");
      while (prefix[i] && i < 32)
-     {
          prefix[++i] = strtok(NULL, ";");
-     }

      /* Parse the desired table types to return */
      show_system_tables = FALSE;
--- 1155,1166 ----
***************
*** 1216,1222 ****
                  show_regular_tables = TRUE;
              else if (strstr(table_type[i], "VIEW"))
                  show_views = TRUE;
-
              i++;
          }
      }
--- 1188,1193 ----
***************
*** 1243,1263 ****
              strcat(tables_query, prefix[i]);
              i++;
          }
-
          strcat(tables_query, "'");
      }

-
      /* match users */
!     if (PG_VERSION_LT(conn, 7.1))        /* filter out large objects in
!                                          * older versions */
          strcat(tables_query, " and relname !~ '^xinv[0-9]+'");

      strcat(tables_query, " and usesysid = relowner");
      strcat(tables_query, " order by relname");

-     /* ********************************************************************** */
-
      result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
      {
--- 1214,1230 ----
              strcat(tables_query, prefix[i]);
              i++;
          }
          strcat(tables_query, "'");
      }

      /* match users */
!     if (PG_VERSION_LT(conn, 7.1))
!         /* filter out large objects in older versions */
          strcat(tables_query, " and relname !~ '^xinv[0-9]+'");

      strcat(tables_query, " and usesysid = relowner");
      strcat(tables_query, " order by relname");

      result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
      {
***************
*** 1330,1336 ****
      result = SQLFetch(htbl_stmt);
      while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
      {
-
          /*
           * Determine if this table name is a system table. If treating
           * system tables as regular tables, then no need to do this test.
--- 1297,1302 ----
***************
*** 1338,1349 ****
          systable = FALSE;
          if (!atoi(ci->show_system_tables))
          {
-
              if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)
                  systable = TRUE;

              else
!             {                    /* Check extra system table prefixes */
                  i = 0;
                  while (prefix[i])
                  {
--- 1304,1315 ----
          systable = FALSE;
          if (!atoi(ci->show_system_tables))
          {
              if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)
                  systable = TRUE;

              else
!             {
!                 /* Check extra system table prefixes */
                  i = 0;
                  while (prefix[i])
                  {
***************
*** 1359,1366 ****
          }

          /* Determine if the table name is a view */
!         if (PG_VERSION_GE(conn, 7.1))    /* view is represented by its
!                                          * relkind since 7.1 */
              view = (relkind_or_hasrules[0] == 'v');
          else
              view = (relkind_or_hasrules[0] == '1');
--- 1325,1332 ----
          }

          /* Determine if the table name is a view */
!         if (PG_VERSION_GE(conn, 7.1))
!             /* view is represented by its relkind since 7.1 */
              view = (relkind_or_hasrules[0] == 'v');
          else
              view = (relkind_or_hasrules[0] == '1');
***************
*** 1379,1394 ****
              (view && show_views) ||
              (regular_table && show_regular_tables))
          {
-
              row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));

              set_tuplefield_string(&row->tuple[0], "");

!             /* I have to hide the table owner from Access, otherwise it */
!             /* insists on referring to the table as 'owner.table'. */
!             /* (this is valid according to the ODBC SQL grammar, but */
!             /* Postgres won't support it.) */
!             /* set_tuplefield_string(&row->tuple[1], table_owner); */

              mylog("SQLTables: table_name = '%s'\n", table_name);

--- 1345,1362 ----
              (view && show_views) ||
              (regular_table && show_regular_tables))
          {
              row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));

              set_tuplefield_string(&row->tuple[0], "");

!             /*
!              * I have to hide the table owner from Access, otherwise it
!              * insists on referring to the table as 'owner.table'.
!              * (this is valid according to the ODBC SQL grammar, but
!              * Postgres won't support it.)
!              *
!              * set_tuplefield_string(&row->tuple[1], table_owner);
!              */

              mylog("SQLTables: table_name = '%s'\n", table_name);

***************
*** 1410,1417 ****
          return SQL_ERROR;
      }

!     /* also, things need to think that this statement is finished so */
!     /* the results can be retrieved. */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
--- 1378,1387 ----
          return SQL_ERROR;
      }

!     /*
!      * also, things need to think that this statement is finished so
!      * the results can be retrieved.
!      */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
***************
*** 1425,1432 ****
  }


-
-
  RETCODE SQL_API
  SQLColumns(
             HSTMT hstmt,
--- 1395,1400 ----
***************
*** 1479,1491 ****
      conn = (ConnectionClass *) (stmt->hdbc);
      ci = &stmt->hdbc->connInfo;

-     /* ********************************************************************** */
-
      /*
       * Create the query to find out the columns (Note: pre 6.3 did not
       * have the atttypmod field)
       */
-     /* ********************************************************************** */
      sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid"
         ", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
              " from pg_user u, pg_class c, pg_attribute a, pg_type t"
--- 1447,1456 ----
***************
*** 1497,1506 ****
      my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
      my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName);

!     /* give the output in the order the columns were defined */
!     /* when the table was created */
      strcat(columns_query, " order by attnum");
-     /* ********************************************************************** */

      result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
--- 1462,1472 ----
      my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
      my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName);

!     /*
!      * give the output in the order the columns were defined
!      * when the table was created
!      */
      strcat(columns_query, " order by attnum");

      result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
***************
*** 1673,1682 ****
      QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
      QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);

-
      result = SQLFetch(hcol_stmt);

-
      /*
       * Only show oid if option AND there are other columns AND it's not
       * being called by SQLStatistics . Always show OID if it's a system
--- 1639,1646 ----
***************
*** 1685,1696 ****

      if (result != SQL_ERROR && !stmt->internal)
      {
-
          if (relhasrules[0] != '1' &&
              (atoi(ci->show_oid_column) ||
               strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0))
          {
-
              /* For OID fields */
              the_type = PG_TYPE_OID;
              row = (TupleNode *) malloc(sizeof(TupleNode) +
--- 1649,1658 ----
***************
*** 1718,1724 ****

              QR_add_tuple(stmt->result, row);
          }
-
      }

      while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
--- 1680,1685 ----
***************
*** 1776,1786 ****
              }
          }

-
          if ((field_type == PG_TYPE_VARCHAR) ||
              (field_type == PG_TYPE_BPCHAR))
          {
-
              useStaticPrecision = FALSE;

              if (mod_length >= 4)
--- 1737,1745 ----
***************
*** 1827,1834 ****
          return SQL_ERROR;
      }

!     /* Put the row version column at the end so it might not be */
!     /* mistaken for a key field. */
      if (relhasrules[0] != '1' && !stmt->internal && atoi(ci->row_versioning))
      {
          /* For Row Versioning fields */
--- 1786,1795 ----
          return SQL_ERROR;
      }

!     /*
!      * Put the row version column at the end so it might not be
!      * mistaken for a key field.
!      */
      if (relhasrules[0] != '1' && !stmt->internal && atoi(ci->row_versioning))
      {
          /* For Row Versioning fields */
***************
*** 1855,1862 ****
          QR_add_tuple(stmt->result, row);
      }

!     /* also, things need to think that this statement is finished so */
!     /* the results can be retrieved. */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
--- 1816,1825 ----
          QR_add_tuple(stmt->result, row);
      }

!     /*
!      * also, things need to think that this statement is finished so
!      * the results can be retrieved.
!      */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
***************
*** 1892,1899 ****
      RETCODE        result;
      char        relhasrules[MAX_INFO_STRING];

-
-
      mylog("%s: entering...stmt=%u\n", func, stmt);

      if (!stmt)
--- 1855,1860 ----
***************
*** 1904,1914 ****
      ci = &stmt->hdbc->connInfo;

      stmt->manual_result = TRUE;
-

!     /* ********************************************************************** */
!     /* Create the query to find out if this is a view or not... */
!     /* ********************************************************************** */
      sprintf(columns_query, "select c.relhasrules "
              "from pg_user u, pg_class c where "
              "u.usesysid = c.relowner");
--- 1865,1874 ----
      ci = &stmt->hdbc->connInfo;

      stmt->manual_result = TRUE;

!     /*
!      * Create the query to find out if this is a view or not...
!      */
      sprintf(columns_query, "select c.relhasrules "
              "from pg_user u, pg_class c where "
              "u.usesysid = c.relowner");
***************
*** 1988,1994 ****
          }
          else if (fColType == SQL_ROWVER)
          {
-
              Int2        the_type = PG_TYPE_INT4;

              if (atoi(ci->row_versioning))
--- 1948,1953 ----
***************
*** 2009,2016 ****
          }
      }

-
-
      stmt->status = STMT_FINISHED;
      stmt->currTuple = -1;
      stmt->rowset_start = -1;
--- 1968,1973 ----
***************
*** 2104,2112 ****
      QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4);
      QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);

!
!     /* only use the table name... the owner should be redundant, and */
!     /* we never use qualifiers. */
      table_name = make_string(szTableName, cbTableName, NULL);
      if (!table_name)
      {
--- 2061,2070 ----
      QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4);
      QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);

!     /*
!      * only use the table name... the owner should be redundant, and
!      * we never use qualifiers.
!      */
      table_name = make_string(szTableName, cbTableName, NULL);
      if (!table_name)
      {
***************
*** 2116,2123 ****
          return SQL_ERROR;
      }

!     /* we need to get a list of the field names first, */
!     /* so we can return them later. */
      result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
      {
--- 2074,2083 ----
          return SQL_ERROR;
      }

!     /*
!      * we need to get a list of the field names first,
!      * so we can return them later.
!      */
      result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
      {
***************
*** 2172,2177 ****
--- 2132,2138 ----

          result = SQLFetch(hcol_stmt);
      }
+
      if (result != SQL_NO_DATA_FOUND || total_columns == 0)
      {
          stmt->errormsg = SC_create_errormsg(hcol_stmt); /* "Couldn't get column
***************
*** 2205,2218 ****
      result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query));
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
      {
!         stmt->errormsg = SC_create_errormsg(hindx_stmt);        /* "Couldn't execute
!                                                                  * index query
!                                                                  * (w/SQLExecDirect) in
!                                                                  * SQLStatistics."; */
          stmt->errornumber = indx_stmt->errornumber;
          SQLFreeStmt(hindx_stmt, SQL_DROP);
          goto SEEYA;
-
      }

      /* bind the index name column */
--- 2166,2180 ----
      result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query));
      if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
      {
!         /*
!          *    "Couldn't execute index query (w/SQLExecDirect) in
!          *    SQLStatistics.";
!          */
!         stmt->errormsg = SC_create_errormsg(hindx_stmt);
!
          stmt->errornumber = indx_stmt->errornumber;
          SQLFreeStmt(hindx_stmt, SQL_DROP);
          goto SEEYA;
      }

      /* bind the index name column */
***************
*** 2314,2320 ****
      result = SQLFetch(hindx_stmt);
      while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
      {
-
          /* If only requesting unique indexs, then just return those. */
          if (fUnique == SQL_INDEX_ALL ||
              (fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
--- 2276,2281 ----
***************
*** 2323,2329 ****
              /* add a row in this table for each field in the index */
              while (i < 16 && fields_vector[i] != 0)
              {
-
                  row = (TupleNode *) malloc(sizeof(TupleNode) +
                                             (13 - 1) *sizeof(TupleField));

--- 2284,2289 ----
***************
*** 2380,2387 ****
      }
      if (result != SQL_NO_DATA_FOUND)
      {
!         stmt->errormsg = SC_create_errormsg(hindx_stmt);        /* "SQLFetch failed in
!                                                                  * SQLStatistics."; */
          stmt->errornumber = indx_stmt->errornumber;
          SQLFreeStmt(hindx_stmt, SQL_DROP);
          goto SEEYA;
--- 2340,2347 ----
      }
      if (result != SQL_NO_DATA_FOUND)
      {
!         /* "SQLFetch failed in SQLStatistics."; */
!         stmt->errormsg = SC_create_errormsg(hindx_stmt);
          stmt->errornumber = indx_stmt->errornumber;
          SQLFreeStmt(hindx_stmt, SQL_DROP);
          goto SEEYA;
***************
*** 2389,2396 ****

      SQLFreeStmt(hindx_stmt, SQL_DROP);

!     /* also, things need to think that this statement is finished so */
!     /* the results can be retrieved. */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
--- 2349,2358 ----

      SQLFreeStmt(hindx_stmt, SQL_DROP);

!     /*
!      * also, things need to think that this statement is finished so
!      * the results can be retrieved.
!      */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
***************
*** 2418,2423 ****
--- 2380,2386 ----
          return SQL_SUCCESS;
  }

+
  RETCODE SQL_API
  SQLColumnPrivileges(
                      HSTMT hstmt,
***************
*** 2434,2448 ****

      mylog("%s: entering...\n", func);

! /*    Neither Access or Borland care about this. */

      SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
      return SQL_ERROR;
  }


! /* SQLPrimaryKeys()
!  * Retrieve the primary key columns for the specified table.
   */
  RETCODE SQL_API
  SQLPrimaryKeys(
--- 2397,2413 ----

      mylog("%s: entering...\n", func);

!     /*    Neither Access or Borland care about this. */

      SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
      return SQL_ERROR;
  }


! /*
!  *    SQLPrimaryKeys()
!  *
!  *    Retrieve the primary key columns for the specified table.
   */
  RETCODE SQL_API
  SQLPrimaryKeys(
***************
*** 2572,2578 ****

      while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
      {
-
          row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));

          set_tuplefield_null(&row->tuple[0]);
--- 2537,2542 ----
***************
*** 2608,2615 ****
      SQLFreeStmt(htbl_stmt, SQL_DROP);


!     /* also, things need to think that this statement is finished so */
!     /* the results can be retrieved. */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
--- 2572,2581 ----
      SQLFreeStmt(htbl_stmt, SQL_DROP);


!     /*
!      * also, things need to think that this statement is finished so
!      * the results can be retrieved.
!      */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
***************
*** 2621,2626 ****
--- 2587,2593 ----
      return SQL_SUCCESS;
  }

+
  RETCODE SQL_API
  SQLForeignKeys(
                 HSTMT hstmt,
***************
*** 2667,2681 ****

  #if (ODBCVER >= 0x0300)
      SWORD        defer_type;
-
  #endif
      char        pkey[MAX_INFO_STRING];
      Int2        result_cols;


-     mylog("%s: entering...stmt=%u\n", func, stmt);
-
-
      if (!stmt)
      {
          SC_log_error(func, "", NULL);
--- 2634,2645 ----

  #if (ODBCVER >= 0x0300)
      SWORD        defer_type;
  #endif
      char        pkey[MAX_INFO_STRING];
      Int2        result_cols;

+      mylog("%s: entering...stmt=%u\n", func, stmt);

      if (!stmt)
      {
          SC_log_error(func, "", NULL);
***************
*** 2723,2730 ****
      QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
  #endif     /* ODBCVER >= 0x0300 */

!     /* also, things need to think that this statement is finished so */
!     /* the results can be retrieved. */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
--- 2687,2696 ----
      QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
  #endif     /* ODBCVER >= 0x0300 */

!     /*
!      * also, things need to think that this statement is finished so
!      * the results can be retrieved.
!      */
      stmt->status = STMT_FINISHED;

      /* set up the current tuple pointer for SQLFetch */
***************
*** 2898,2904 ****

          while (result == SQL_SUCCESS)
          {
-
              /* Compute the number of keyparts. */
              num_keys = (trig_nargs - 4) / 2;

--- 2864,2869 ----
***************
*** 2913,2919 ****
              /* If there is a pk table specified, then check it. */
              if (pk_table_needed[0] != '\0')
              {
-
                  /* If it doesn't match, then continue */
                  if (strcmp(pk_table, pk_table_needed))
                  {
--- 2878,2883 ----
***************
*** 2932,2938 ****
                  return SQL_ERROR;
              }

-
              /* Check that the key listed is the primary key */
              keyresult = SQLFetch(hpkey_stmt);

--- 2896,2901 ----
***************
*** 2949,2955 ****
                      num_keys = 0;
                      break;
                  }
-
                  /* Get to next primary key */
                  for (k = 0; k < 2; k++)
                      pkey_ptr += strlen(pkey_ptr) + 1;
--- 2912,2917 ----
***************
*** 3002,3008 ****

              for (k = 0; k < num_keys; k++)
              {
-
                  row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));

                  mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr);
--- 2964,2969 ----
***************
*** 3050,3056 ****
       */
      else if (pk_table_needed[0] != '\0')
      {
-
          sprintf(tables_query, "SELECT    pg_trigger.tgargs, "
                  "        pg_trigger.tgnargs, "
                  "        pg_trigger.tgdeferrable, "
--- 3011,3016 ----
***************
*** 3172,3178 ****

          while (result == SQL_SUCCESS)
          {
-
              /* Calculate the number of key parts */
              num_keys = (trig_nargs - 4) / 2;;

--- 3132,3137 ----
***************
*** 3216,3222 ****
              for (i = 0; i < 5; i++)
                  pkey_ptr += strlen(pkey_ptr) + 1;

-
              /* Get to first foreign table */
              fk_table = trig_args;
              fk_table += strlen(fk_table) + 1;
--- 3175,3180 ----
***************
*** 3228,3234 ****

              for (k = 0; k < num_keys; k++)
              {
-
                  mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_ptr, fk_table, fkey_ptr);

                  row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
--- 3186,3191 ----
***************
*** 3270,3276 ****
                      fkey_ptr += strlen(fkey_ptr) + 1;
                  }
              }
-
              result = SQLFetch(htbl_stmt);
          }
      }
--- 3227,3232 ----
***************
*** 3290,3296 ****
  }


-
  RETCODE SQL_API
  SQLProcedureColumns(
                      HSTMT hstmt,
--- 3246,3251 ----
***************
*** 3311,3316 ****
--- 3266,3272 ----
      return SQL_ERROR;
  }

+
  RETCODE SQL_API
  SQLProcedures(
                HSTMT hstmt,
***************
*** 3328,3333 ****
--- 3284,3290 ----
      SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
      return SQL_ERROR;
  }
+

  RETCODE SQL_API
  SQLTablePrivileges(
Index: src/interfaces/odbc/lobj.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/lobj.c,v
retrieving revision 1.11
diff -c -r1.11 lobj.c
*** src/interfaces/odbc/lobj.c    2001/03/27 04:00:54    1.11
--- src/interfaces/odbc/lobj.c    2001/03/28 16:53:17
***************
*** 1,4 ****
! /* Module:            lobj.c
   *
   * Description:        This module contains routines related to manipulating
   *                    large objects.
--- 1,5 ----
! /*--------
!  * Module:            lobj.c
   *
   * Description:        This module contains routines related to manipulating
   *                    large objects.
***************
*** 8,14 ****
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #include "lobj.h"
--- 9,15 ----
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *--------
   */

  #include "lobj.h"
***************
*** 30,37 ****
          return 0;                /* invalid oid */
      else
          return retval;
-
-
  }

  int
--- 31,36 ----
***************
*** 40,47 ****
      int            fd;
      int            result_len;
      LO_ARG        argv[2];
!
!
      argv[0].isint = 1;
      argv[0].len = 4;
      argv[0].u.integer = lobjId;
--- 39,45 ----
      int            fd;
      int            result_len;
      LO_ARG        argv[2];
!
      argv[0].isint = 1;
      argv[0].len = 4;
      argv[0].u.integer = lobjId;
***************
*** 66,92 ****
      int            retval,
                  result_len;

-
      argv[0].isint = 1;
      argv[0].len = 4;
      argv[0].u.integer = fd;

      if (!CC_send_function(conn, LO_CLOSE, &retval, &result_len, 1, argv, 1))
          return -1;
-
      else
          return retval;
-
  }

-
  int
  lo_read(ConnectionClass *conn, int fd, char *buf, int len)
  {
      LO_ARG        argv[2];
      int            result_len;

-
      argv[0].isint = 1;
      argv[0].len = 4;
      argv[0].u.integer = fd;
--- 64,85 ----
***************
*** 97,103 ****

      if (!CC_send_function(conn, LO_READ, (int *) buf, &result_len, 0, argv, 2))
          return -1;
-
      else
          return result_len;
  }
--- 90,95 ----
***************
*** 109,115 ****
      int            retval,
                  result_len;

-
      if (len <= 0)
          return 0;

--- 101,106 ----
***************
*** 123,129 ****

      if (!CC_send_function(conn, LO_WRITE, &retval, &result_len, 1, argv, 2))
          return -1;
-
      else
          return retval;
  }
--- 114,119 ----
***************
*** 135,141 ****
      int            retval,
                  result_len;

-
      argv[0].isint = 1;
      argv[0].len = 4;
      argv[0].u.integer = fd;
--- 125,130 ----
***************
*** 150,156 ****

      if (!CC_send_function(conn, LO_LSEEK, &retval, &result_len, 1, argv, 3))
          return -1;
-
      else
          return retval;
  }
--- 139,144 ----
***************
*** 162,175 ****
      int            retval,
                  result_len;

-
      argv[0].isint = 1;
      argv[0].len = 4;
      argv[0].u.integer = fd;

      if (!CC_send_function(conn, LO_TELL, &retval, &result_len, 1, argv, 1))
          return -1;
-
      else
          return retval;
  }
--- 150,161 ----
***************
*** 181,194 ****
      int            retval,
                  result_len;

-
      argv[0].isint = 1;
      argv[0].len = 4;
      argv[0].u.integer = lobjId;

      if (!CC_send_function(conn, LO_UNLINK, &retval, &result_len, 1, argv, 1))
          return -1;
-
      else
          return retval;
  }
--- 167,178 ----
Index: src/interfaces/odbc/misc.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/misc.c,v
retrieving revision 1.20
diff -c -r1.20 misc.c
*** src/interfaces/odbc/misc.c    2001/03/27 04:00:54    1.20
--- src/interfaces/odbc/misc.c    2001/03/28 16:53:17
***************
*** 1,4 ****
! /* Module:            misc.c
   *
   * Description:        This module contains miscellaneous routines
   *                    such as for debugging/logging and string functions.
--- 1,5 ----
! /*-------
!  * Module:            misc.c
   *
   * Description:        This module contains miscellaneous routines
   *                    such as for debugging/logging and string functions.
***************
*** 8,14 ****
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #include <stdio.h>
--- 9,15 ----
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #include <stdio.h>
***************
*** 83,89 ****
          va_end(args);
      }
  }
-
  #endif


--- 84,89 ----
***************
*** 114,120 ****
          va_end(args);
      }
  }
-
  #endif

  /*    Undefine these because windows.h will redefine and cause a warning */
--- 114,119 ----
***************
*** 137,143 ****
  #endif


! /*    returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied (not including null term) */
  int
  my_strcpy(char *dst, int dst_len, char *src, int src_len)
  {
--- 136,145 ----
  #endif


! /*
!  *    returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied
!  *    (not including null term)
!  */
  int
  my_strcpy(char *dst, int dst_len, char *src, int src_len)
  {
***************
*** 154,160 ****

      if (src_len <= 0)
          return STRCPY_FAIL;
-
      else
      {
          if (src_len < dst_len)
--- 156,161 ----
***************
*** 173,182 ****
      return strlen(dst);
  }

! /* strncpy copies up to len characters, and doesn't terminate */
! /* the destination string if src has len characters or more. */
! /* instead, I want it to copy up to len-1 characters and always */
! /* terminate the destination string. */
  char *
  strncpy_null(char *dst, const char *src, int len)
  {
--- 174,185 ----
      return strlen(dst);
  }

! /*
!  * strncpy copies up to len characters, and doesn't terminate
!  * the destination string if src has len characters or more.
!  * instead, I want it to copy up to len-1 characters and always
!  * terminate the destination string.
!  */
  char *
  strncpy_null(char *dst, const char *src, int len)
  {
***************
*** 185,191 ****

      if (NULL != dst)
      {
-
          /* Just in case, check for special lengths */
          if (len == SQL_NULL_DATA)
          {
--- 188,193 ----
***************
*** 204,212 ****
      return dst;
  }

! /*    Create a null terminated string (handling the SQL_NTS thing): */
! /*        1. If buf is supplied, place the string in there (assumes enough space) and return buf. */
! /*        2. If buf is not supplied, malloc space and return this string */
  char *
  make_string(char *s, int len, char *buf)
  {
--- 206,218 ----
      return dst;
  }

! /*------
!  *    Create a null terminated string (handling the SQL_NTS thing):
!  *        1. If buf is supplied, place the string in there
!  *           (assumes enough space) and return buf.
!  *        2. If buf is not supplied, malloc space and return this string
!  *------
!  */
  char *
  make_string(char *s, int len, char *buf)
  {
***************
*** 234,247 ****
      return NULL;
  }

! /*    Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing. */
! /*    "fmt" must contain somewhere in it the single form '%.*s' */
! /*    This is heavily used in creating queries for info routines (SQLTables, SQLColumns). */
! /*    This routine could be modified to use vsprintf() to handle multiple arguments. */
  char *
  my_strcat(char *buf, char *fmt, char *s, int len)
  {
-
      if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
      {
          int            length = (len > 0) ? len : strlen(s);
--- 240,254 ----
      return NULL;
  }

! /*
!  *    Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing.
!  *    "fmt" must contain somewhere in it the single form '%.*s'.
!  *    This is heavily used in creating queries for info routines (SQLTables, SQLColumns).
!  *    This routine could be modified to use vsprintf() to handle multiple arguments.
!  */
  char *
  my_strcat(char *buf, char *fmt, char *s, int len)
  {
      if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
      {
          int            length = (len > 0) ? len : strlen(s);
Index: src/interfaces/odbc/multibyte.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/multibyte.c,v
retrieving revision 1.5
diff -c -r1.5 multibyte.c
*** src/interfaces/odbc/multibyte.c    2001/03/27 04:00:54    1.5
--- src/interfaces/odbc/multibyte.c    2001/03/28 16:53:17
***************
*** 1,10 ****
! /*
   * Module :            multibyte.c
   *
   * Description:        Mlutibyte related additional function.
   *
   *                    Create 2001-03-03 Eiji Tokuya
!  *
   */

  #include <string.h>
--- 1,10 ----
! /*--------
   * Module :            multibyte.c
   *
   * Description:        Mlutibyte related additional function.
   *
   *                    Create 2001-03-03 Eiji Tokuya
!  *--------
   */

  #include <string.h>
***************
*** 36,42 ****
                  }
                  break;

-
  /* Chinese Big5 Support. */
              case BIG5:
                  {
--- 36,41 ----
***************
*** 81,99 ****
      return ("OHTER");
  }

! /*
   * Multibyte Status Function.
   *    Input    char
   *    Output    0    : 1 Byte Character.
   *            1    : MultibyteCharacter Last Byte.
   *            N    : MultibyteCharacter Fast or Middle Byte.
   */
  int
  multibyte_char_check(unsigned char s)
  {
      switch (multibyte_client_encoding)
      {
! /* Japanese Shift-JIS(CP932) Support. */
              case SJIS:
              {
                  if (multibyte_status < 2 && s > 0x80 && !(s > 0x9f && s < 0xE0))
--- 80,99 ----
      return ("OHTER");
  }

! /*--------
   * Multibyte Status Function.
   *    Input    char
   *    Output    0    : 1 Byte Character.
   *            1    : MultibyteCharacter Last Byte.
   *            N    : MultibyteCharacter Fast or Middle Byte.
+  *--------
   */
  int
  multibyte_char_check(unsigned char s)
  {
      switch (multibyte_client_encoding)
      {
!             /* Japanese Shift-JIS(CP932) Support. */
              case SJIS:
              {
                  if (multibyte_status < 2 && s > 0x80 && !(s > 0x9f && s < 0xE0))
***************
*** 104,124 ****
                      multibyte_status = 0;
              }
              break;
-

! /* Chinese Big5(CP950) Support. */
!         case BIG5:
!             {
!                 if (multibyte_status < 2 && s > 0xA0)
!                     multibyte_status = 2;
!                 else if (multibyte_status == 2)
!                     multibyte_status = 1;
!                 else
!                     multibyte_status = 0;
!             }
!             break;
!         default:
!             multibyte_status = 0;
      }
  #ifdef _DEBUG
      qlog("multibyte_client_encoding = %d   s = 0x%02X   multibyte_stat = %d\n", multibyte_client_encoding, s,
multibyte_status);
--- 104,123 ----
                      multibyte_status = 0;
              }
              break;

!             /* Chinese Big5(CP950) Support. */
!             case BIG5:
!                 {
!                     if (multibyte_status < 2 && s > 0xA0)
!                         multibyte_status = 2;
!                     else if (multibyte_status == 2)
!                         multibyte_status = 1;
!                     else
!                         multibyte_status = 0;
!                 }
!                 break;
!             default:
!                 multibyte_status = 0;
      }
  #ifdef _DEBUG
      qlog("multibyte_client_encoding = %d   s = 0x%02X   multibyte_stat = %d\n", multibyte_client_encoding, s,
multibyte_status);
Index: src/interfaces/odbc/options.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/options.c,v
retrieving revision 1.27
diff -c -r1.27 options.c
*** src/interfaces/odbc/options.c    2001/03/27 04:00:54    1.27
--- src/interfaces/odbc/options.c    2001/03/28 16:53:18
***************
*** 1,4 ****
! /* Module:            options.c
   *
   * Description:        This module contains routines for getting/setting
   *                    connection and statement options.
--- 1,5 ----
! /*--------
!  * Module:            options.c
   *
   * Description:        This module contains routines for getting/setting
   *                    connection and statement options.
***************
*** 9,15 ****
   *                    SQLGetStmtOption
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 10,16 ----
   *                    SQLGetStmtOption
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *--------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 43,49 ****
                       UDWORD vParam);


-
  RETCODE
  set_statement_option(ConnectionClass *conn,
                       StatementClass *stmt,
--- 44,49 ----
***************
*** 53,59 ****
      static char *func = "set_statement_option";
      char        changed = FALSE;

-
      switch (fOption)
      {
          case SQL_ASYNC_ENABLE:    /* ignored */
--- 53,58 ----
***************
*** 68,79 ****
              break;

          case SQL_CONCURRENCY:
-
              /*
               * positioned update isn't supported so cursor concurrency is
               * read-only
               */
-
              if (conn)
                  conn->stmtOptions.scroll_concurrency = vParam;
              if (stmt)
--- 67,76 ----
***************
*** 104,110 ****
               */

          case SQL_CURSOR_TYPE:
-
              /*
               * if declare/fetch, then type can only be forward. otherwise,
               * it can only be forward or static.
--- 101,106 ----
***************
*** 113,130 ****

              if (globals.lie)
              {
-
                  if (conn)
                      conn->stmtOptions.cursor_type = vParam;
                  if (stmt)
                      stmt->options.cursor_type = vParam;
-
              }
              else
              {
                  if (globals.use_declarefetch)
                  {
-
                      if (conn)
                          conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY;
                      if (stmt)
--- 109,123 ----
***************
*** 137,143 ****
                  {
                      if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
                      {
-
                          if (conn)
                              conn->stmtOptions.cursor_type = vParam;        /* valid type */
                          if (stmt)
--- 130,135 ----
***************
*** 145,151 ****
                      }
                      else
                      {
-
                          if (conn)
                              conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC;
                          if (stmt)
--- 137,142 ----
***************
*** 167,180 ****

              break;

!             /*
!              * if (globals.lie) stmt->keyset_size = vParam; else {
!              * stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
!              * stmt->errormsg = "Driver does not support keyset size
!              * option"; SC_log_error(func, "", stmt); return SQL_ERROR; }
               */

!         case SQL_MAX_LENGTH:    /* ignored, but saved */
              mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %d\n", vParam);
              if (conn)
                  conn->stmtOptions.maxLength = vParam;
--- 158,177 ----

              break;

!             /*-------
!              *    if (globals.lie)
!              *        stmt->keyset_size = vParam;
!              *    else
!              *    {
!              *        stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
!              *        stmt->errormsg = "Driver does not support keyset size option";
!              *        SC_log_error(func, "", stmt);
!              *        return SQL_ERROR;
!              *    }
!              *-------
               */

!         case SQL_MAX_LENGTH:        /* ignored, but saved */
              mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %d\n", vParam);
              if (conn)
                  conn->stmtOptions.maxLength = vParam;
***************
*** 182,188 ****
                  stmt->options.maxLength = vParam;
              break;

!         case SQL_MAX_ROWS:        /* ignored, but saved */
              mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam);
              if (conn)
                  conn->stmtOptions.maxRows = vParam;
--- 179,185 ----
                  stmt->options.maxLength = vParam;
              break;

!         case SQL_MAX_ROWS:            /* ignored, but saved */
              mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam);
              if (conn)
                  conn->stmtOptions.maxRows = vParam;
***************
*** 190,205 ****
                  stmt->options.maxRows = vParam;
              break;

!         case SQL_NOSCAN:        /* ignored */
              mylog("SetStmtOption: SQL_NOSCAN, vParam = %d\n", vParam);
              break;

!         case SQL_QUERY_TIMEOUT:/* ignored */
              mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d\n", vParam);
              /* "0" returned in SQLGetStmtOption */
              break;

!         case SQL_RETRIEVE_DATA:/* ignored, but saved */
              mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam);
              if (conn)
                  conn->stmtOptions.retrieve_data = vParam;
--- 187,202 ----
                  stmt->options.maxRows = vParam;
              break;

!         case SQL_NOSCAN:            /* ignored */
              mylog("SetStmtOption: SQL_NOSCAN, vParam = %d\n", vParam);
              break;

!         case SQL_QUERY_TIMEOUT:        /* ignored */
              mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d\n", vParam);
              /* "0" returned in SQLGetStmtOption */
              break;

!         case SQL_RETRIEVE_DATA:        /* ignored, but saved */
              mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam);
              if (conn)
                  conn->stmtOptions.retrieve_data = vParam;
***************
*** 210,216 ****
          case SQL_ROWSET_SIZE:
              mylog("SetStmtOption(): SQL_ROWSET_SIZE, vParam = %d\n", vParam);

-
              /*
               * Save old rowset size for SQLExtendedFetch purposes If the
               * rowset_size is being changed since the last call to fetch
--- 207,212 ----
***************
*** 230,236 ****
                  conn->stmtOptions.rowset_size = vParam;
              if (stmt)
                  stmt->options.rowset_size = vParam;
-
              break;

          case SQL_SIMULATE_CURSOR:        /* NOT SUPPORTED */
--- 226,231 ----
***************
*** 249,255 ****
              return SQL_ERROR;

          case SQL_USE_BOOKMARKS:
-
              if (stmt)
                  stmt->options.use_bookmarks = vParam;
              if (conn)
--- 244,249 ----
***************
*** 298,304 ****
  }


-
  /* Implements only SQL_AUTOCOMMIT */
  RETCODE SQL_API
  SQLSetConnectOption(
--- 292,297 ----
***************
*** 320,333 ****
          return SQL_INVALID_HANDLE;
      }

-
      switch (fOption)
      {
!
!             /*
!              * Statement Options (apply to all stmts on the connection and
!              * become defaults for new stmts)
!              */
          case SQL_ASYNC_ENABLE:
          case SQL_BIND_TYPE:
          case SQL_CONCURRENCY:
--- 313,324 ----
          return SQL_INVALID_HANDLE;
      }

      switch (fOption)
      {
!         /*
!          * Statement Options (apply to all stmts on the connection and
!          * become defaults for new stmts)
!          */
          case SQL_ASYNC_ENABLE:
          case SQL_BIND_TYPE:
          case SQL_CONCURRENCY:
***************
*** 362,376 ****

              break;

!             /**********************************/
!             /*****    Connection Options    *******/
!             /**********************************/

          case SQL_ACCESS_MODE:    /* ignored */
              break;

          case SQL_AUTOCOMMIT:
-
              if (CC_is_in_trans(conn))
              {
                  conn->errormsg = "Cannot switch commit mode while a transaction is in progress";
--- 353,366 ----

              break;

!         /*
!          *    Connection Options
!          */

          case SQL_ACCESS_MODE:    /* ignored */
              break;

          case SQL_AUTOCOMMIT:
              if (CC_is_in_trans(conn))
              {
                  conn->errormsg = "Cannot switch commit mode while a transaction is in progress";
***************
*** 397,409 ****
                      CC_log_error(func, "", conn);
                      return SQL_ERROR;
              }
-
              break;

          case SQL_CURRENT_QUALIFIER:        /* ignored */
              break;

!         case SQL_LOGIN_TIMEOUT:/* ignored */
              break;

          case SQL_PACKET_SIZE:    /* ignored */
--- 387,398 ----
                      CC_log_error(func, "", conn);
                      return SQL_ERROR;
              }
              break;

          case SQL_CURRENT_QUALIFIER:        /* ignored */
              break;

!         case SQL_LOGIN_TIMEOUT:    /* ignored */
              break;

          case SQL_PACKET_SIZE:    /* ignored */
***************
*** 412,421 ****
          case SQL_QUIET_MODE:    /* ignored */
              break;

!         case SQL_TXN_ISOLATION:/* ignored */
              break;

!             /* These options should be handled by driver manager */
          case SQL_ODBC_CURSORS:
          case SQL_OPT_TRACE:
          case SQL_OPT_TRACEFILE:
--- 401,410 ----
          case SQL_QUIET_MODE:    /* ignored */
              break;

!         case SQL_TXN_ISOLATION:    /* ignored */
              break;

!         /* These options should be handled by driver manager */
          case SQL_ODBC_CURSORS:
          case SQL_OPT_TRACE:
          case SQL_OPT_TRACEFILE:
***************
*** 434,440 ****
                  CC_log_error(func, option, conn);
                  return SQL_ERROR;
              }
-
      }

      if (changed)
--- 423,428 ----
***************
*** 447,453 ****
          return SQL_SUCCESS;
  }

- /*        -        -        -        -        -        -        -        -        - */

  /* This function just can tell you whether you are in Autcommit mode or not */
  RETCODE SQL_API
--- 435,440 ----
***************
*** 469,475 ****

      switch (fOption)
      {
!         case SQL_ACCESS_MODE:    /* NOT SUPPORTED */
              *((UDWORD *) pvParam) = SQL_MODE_READ_WRITE;
              break;

--- 456,462 ----

      switch (fOption)
      {
!         case SQL_ACCESS_MODE:        /* NOT SUPPORTED */
              *((UDWORD *) pvParam) = SQL_MODE_READ_WRITE;
              break;

***************
*** 484,506 ****

              break;

!         case SQL_LOGIN_TIMEOUT:/* NOT SUPPORTED */
              *((UDWORD *) pvParam) = 0;
              break;

!         case SQL_PACKET_SIZE:    /* NOT SUPPORTED */
              *((UDWORD *) pvParam) = globals.socket_buffersize;
              break;

!         case SQL_QUIET_MODE:    /* NOT SUPPORTED */
              *((UDWORD *) pvParam) = (UDWORD) NULL;
              break;

!         case SQL_TXN_ISOLATION:/* NOT SUPPORTED */
              *((UDWORD *) pvParam) = SQL_TXN_SERIALIZABLE;
              break;

!             /* These options should be handled by driver manager */
          case SQL_ODBC_CURSORS:
          case SQL_OPT_TRACE:
          case SQL_OPT_TRACEFILE:
--- 471,493 ----

              break;

!         case SQL_LOGIN_TIMEOUT:        /* NOT SUPPORTED */
              *((UDWORD *) pvParam) = 0;
              break;

!         case SQL_PACKET_SIZE:        /* NOT SUPPORTED */
              *((UDWORD *) pvParam) = globals.socket_buffersize;
              break;

!         case SQL_QUIET_MODE:        /* NOT SUPPORTED */
              *((UDWORD *) pvParam) = (UDWORD) NULL;
              break;

!         case SQL_TXN_ISOLATION:        /* NOT SUPPORTED */
              *((UDWORD *) pvParam) = SQL_TXN_SERIALIZABLE;
              break;

!         /* These options should be handled by driver manager */
          case SQL_ODBC_CURSORS:
          case SQL_OPT_TRACE:
          case SQL_OPT_TRACEFILE:
***************
*** 520,532 ****
                  return SQL_ERROR;
                  break;
              }
-
      }

      return SQL_SUCCESS;
  }

- /*        -        -        -        -        -        -        -        -        - */

  RETCODE SQL_API
  SQLSetStmtOption(
--- 507,517 ----
***************
*** 538,548 ****
      StatementClass *stmt = (StatementClass *) hstmt;

      mylog("%s: entering...\n", func);
-
-     /* thought we could fake Access out by just returning SQL_SUCCESS */
-     /* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */
-     /* and expects the driver to reduce it to the real value */

      if (!stmt)
      {
          SC_log_error(func, "", NULL);
--- 523,534 ----
      StatementClass *stmt = (StatementClass *) hstmt;

      mylog("%s: entering...\n", func);

+     /*
+      *    Though we could fake Access out by just returning SQL_SUCCESS
+      *     all the time, but it tries to set a huge value for SQL_MAX_LENGTH
+      *     and expects the driver to reduce it to the real value.
+      */
      if (!stmt)
      {
          SC_log_error(func, "", NULL);
***************
*** 553,560 ****
  }


- /*        -        -        -        -        -        -        -        -        - */
-
  RETCODE SQL_API
  SQLGetStmtOption(
                   HSTMT hstmt,
--- 539,544 ----
***************
*** 566,576 ****
      QResultClass *res;

      mylog("%s: entering...\n", func);
-
-     /* thought we could fake Access out by just returning SQL_SUCCESS */
-     /* all the time, but it tries to set a huge value for SQL_MAX_LENGTH */
-     /* and expects the driver to reduce it to the real value */

      if (!stmt)
      {
          SC_log_error(func, "", NULL);
--- 550,561 ----
      QResultClass *res;

      mylog("%s: entering...\n", func);

+     /*
+      * thought we could fake Access out by just returning SQL_SUCCESS
+      * all the time, but it tries to set a huge value for SQL_MAX_LENGTH
+      * and expects the driver to reduce it to the real value
+      */
      if (!stmt)
      {
          SC_log_error(func, "", NULL);
***************
*** 689,693 ****

      return SQL_SUCCESS;
  }
-
- /*        -        -        -        -        -        -        -        -        - */
--- 674,676 ----
Index: src/interfaces/odbc/parse.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/parse.c,v
retrieving revision 1.16
diff -c -r1.16 parse.c
*** src/interfaces/odbc/parse.c    2001/03/27 04:00:54    1.16
--- src/interfaces/odbc/parse.c    2001/03/28 16:53:18
***************
*** 1,20 ****
! /* Module:            parse.c
   *
!  * Description:        This module contains routines related to parsing SQL statements.
!  *                    This can be useful for two reasons:
   *
!  *                    1. So the query does not actually have to be executed to return data about it
   *
!  *                    2. To be able to return information about precision, nullability, aliases, etc.
!  *                       in the functions SQLDescribeCol and SQLColAttributes.  Currently, Postgres
!  *                       doesn't return any information about these things in a query.
   *
   * Classes:            none
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */
  /* Multibyte support    Eiji Tokuya 2001-03-15 */

--- 1,24 ----
! /*--------
!  * Module:            parse.c
   *
!  * Description:        This module contains routines related to parsing SQL
!  *                    statements.  This can be useful for two reasons:
   *
!  *                    1. So the query does not actually have to be executed
!  *                    to return data about it
   *
!  *                    2. To be able to return information about precision,
!  *                    nullability, aliases, etc. in the functions
!  *                    SQLDescribeCol and SQLColAttributes.  Currently,
!  *                    Postgres doesn't return any information about
!  *                    these things in a query.
   *
   * Classes:            none
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *--------
   */
  /* Multibyte support    Eiji Tokuya 2001-03-15 */

***************
*** 87,93 ****
      while (!isspace((unsigned char) s[i]) && s[i] != ',' &&
             s[i] != '\0' && out != smax)
      {
-
          /* Handle quoted stuff */
          if (out == 0 && (s[i] == '\"' || s[i] == '\''))
          {
--- 91,96 ----
***************
*** 225,237 ****
      fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
  }

  char
  searchColInfo(COL_INFO *col_info, FIELD_INFO *fi)
  {
      int            k;
      char       *col;

-
      for (k = 0; k < QR_get_num_tuples(col_info->result); k++)
      {
          col = QR_get_value_manual(col_info->result, k, 3);
--- 228,240 ----
      fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
  }

+
  char
  searchColInfo(COL_INFO *col_info, FIELD_INFO *fi)
  {
      int            k;
      char       *col;

      for (k = 0; k < QR_get_num_tuples(col_info->result); k++)
      {
          col = QR_get_value_manual(col_info->result, k, 3);
***************
*** 283,289 ****
      StatementClass *col_stmt;
      RETCODE        result;

-
      mylog("%s: entering...\n", func);

      ptr = stmt->statement;
--- 286,291 ----
***************
*** 295,301 ****

      while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL)
      {
-
          unquoted = !(quote || dquote);

          mylog("unquoted=%d, quote=%d, dquote=%d, numeric=%d, delim='%c', token='%s', ptr='%s'\n", unquoted, quote,
dquote,numeric, delim, token, ptr); 
--- 297,302 ----
***************
*** 339,345 ****
                           !stricmp(token, "group") ||
                           !stricmp(token, "having")))
          {
-
              in_select = FALSE;
              in_from = FALSE;
              in_where = TRUE;
--- 340,345 ----
***************
*** 350,356 ****

          if (in_select)
          {
-
              if (in_distinct)
              {
                  mylog("in distinct\n");
--- 350,355 ----
***************
*** 372,378 ****
              }

              if (in_expr || in_func)
!             {                    /* just eat the expression */
                  mylog("in_expr=%d or func=%d\n", in_expr, in_func);
                  if (quote || dquote)
                      continue;
--- 371,378 ----
              }

              if (in_expr || in_func)
!             {
!                 /* just eat the expression */
                  mylog("in_expr=%d or func=%d\n", in_expr, in_func);
                  if (quote || dquote)
                      continue;
***************
*** 383,389 ****
                      in_expr = FALSE;
                      in_field = FALSE;
                  }
-
                  else if (token[0] == '(')
                  {
                      blevel++;
--- 383,388 ----
***************
*** 405,411 ****

              if (!in_field)
              {
-
                  if (!token[0])
                      continue;

--- 404,409 ----
***************
*** 453,459 ****
                      blevel = 1;
                      continue;
                  }
-
                  else
                  {
                      strcpy(fi[stmt->nfld]->name, token);
--- 451,456 ----
***************
*** 469,477 ****
                  continue;
              }

!             /**************************/
!             /* We are in a field now */
!             /**************************/
              if (in_dot)
              {
                  stmt->nfld--;
--- 466,474 ----
                  continue;
              }

!             /*
!              * We are in a field now
!              */
              if (in_dot)
              {
                  stmt->nfld--;
***************
*** 485,491 ****
                      mylog("in_dot: got comma\n");
                      in_field = FALSE;
                  }
-
                  continue;
              }

--- 482,487 ----
***************
*** 538,549 ****
              fi[stmt->nfld - 1]->expr = TRUE;
              fi[stmt->nfld - 1]->name[0] = '\0';
              mylog("*** setting expression\n");
-
          }

          if (in_from)
          {
-
              if (!in_table)
              {
                  if (!token[0])
--- 534,543 ----
***************
*** 586,603 ****
                  mylog("more than 1 tables\n");
          }
      }
-

!     /*************************************************/
!     /* Resolve any possible field names with tables */
!     /*************************************************/

      parse = TRUE;

      /* Resolve field names with tables */
      for (i = 0; i < stmt->nfld; i++)
      {
-
          if (fi[i]->func || fi[i]->expr || fi[i]->numeric)
          {
              fi[i]->ti = NULL;
--- 580,595 ----
                  mylog("more than 1 tables\n");
          }
      }

!     /*
!      * Resolve any possible field names with tables
!      */

      parse = TRUE;

      /* Resolve field names with tables */
      for (i = 0; i < stmt->nfld; i++)
      {
          if (fi[i]->func || fi[i]->expr || fi[i]->numeric)
          {
              fi[i]->ti = NULL;
***************
*** 605,611 ****
              parse = FALSE;
              continue;
          }
-
          else if (fi[i]->quote)
          {                        /* handle as text */
              fi[i]->ti = NULL;
--- 597,602 ----
***************
*** 613,619 ****
              fi[i]->precision = 0;
              continue;
          }
-
          /* it's a dot, resolve to table or alias */
          else if (fi[i]->dot[0])
          {
--- 604,609 ----
***************
*** 648,663 ****
      for (i = 0; i < stmt->ntab; i++)
          mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias);

-
-     /******************************************************/
-     /* Now save the SQLColumns Info for the parse tables */
-     /******************************************************/


      /* Call SQLColumns for each table and store the result */
      for (i = 0; i < stmt->ntab; i++)
      {
-
          /* See if already got it */
          char        found = FALSE;

--- 638,651 ----
      for (i = 0; i < stmt->ntab; i++)
          mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias);


+     /*
+      * Now save the SQLColumns Info for the parse tables
+      */

      /* Call SQLColumns for each table and store the result */
      for (i = 0; i < stmt->ntab; i++)
      {
          /* See if already got it */
          char        found = FALSE;

***************
*** 673,679 ****

          if (!found)
          {
-
              mylog("PARSE: Getting SQLColumns for table[%d]='%s'\n", i, ti[i]->name);

              result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
--- 661,666 ----
***************
*** 697,703 ****
                  mylog("      Success\n");
                  if (!(conn->ntables % COL_INCR))
                  {
-
                      mylog("PARSE: Allocing col_info at ntables=%d\n", conn->ntables);

                      conn->col_info = (COL_INFO **) realloc(conn->col_info, (conn->ntables + COL_INCR) *
sizeof(COL_INFO*)); 
--- 684,689 ----
***************
*** 746,763 ****
          mylog("associate col_info: i=%d, k=%d\n", i, k);
      }

-
      mylog("Done SQLColumns\n");
-
-     /******************************************************/
-     /* Now resolve the fields to point to column info     */
-     /******************************************************/
-

!
      for (i = 0; i < stmt->nfld;)
      {
-
          /* Dont worry about functions or quotes */
          if (fi[i]->func || fi[i]->quote || fi[i]->numeric)
          {
--- 732,744 ----
          mylog("associate col_info: i=%d, k=%d\n", i, k);
      }

      mylog("Done SQLColumns\n");

!     /*
!      * Now resolve the fields to point to column info
!      */
      for (i = 0; i < stmt->nfld;)
      {
          /* Dont worry about functions or quotes */
          if (fi[i]->func || fi[i]->quote || fi[i]->numeric)
          {
***************
*** 768,774 ****
          /* Stars get expanded to all fields in the table */
          else if (fi[i]->name[0] == '*')
          {
-
              char        do_all_tables;
              int            total_cols,
                          old_alloc,
--- 749,754 ----
***************
*** 794,800 ****
              increased_cols = total_cols - 1;

              /* Allocate some more field pointers if necessary */
-             /*------------------------------------------------------------- */
              old_alloc = ((stmt->nfld - 1) / FLD_INCR + 1) * FLD_INCR;
              new_size = stmt->nfld + increased_cols;

--- 774,779 ----
***************
*** 814,821 ****
                  stmt->fi = fi;
              }

-             /*------------------------------------------------------------- */
-
              /*
               * copy any other fields (if there are any) up past the
               * expansion
--- 793,798 ----
***************
*** 827,847 ****
              }
              mylog("done copying fields\n");

-             /*------------------------------------------------------------- */
              /* Set the new number of fields */
              stmt->nfld += increased_cols;
              mylog("stmt->nfld now at %d\n", stmt->nfld);


-             /*------------------------------------------------------------- */
              /* copy the new field info */
-
-
              do_all_tables = (fi[i]->ti ? FALSE : TRUE);

              for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++)
              {
-
                  TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti;

                  cols = QR_get_num_tuples(the_ti->col_info->result);
--- 804,819 ----
***************
*** 874,881 ****
                  i += cols;
                  mylog("i now at %d\n", i);
              }
-
-             /*------------------------------------------------------------- */
          }

          /*
--- 846,851 ----
***************
*** 885,891 ****
           */
          else if (fi[i]->ti)
          {
-
              if (!searchColInfo(fi[i]->ti->col_info, fi[i]))
                  parse = FALSE;

--- 855,860 ----
***************
*** 909,920 ****
          }
      }

-
      if (!parse)
          stmt->parse_status = STMT_PARSE_INCOMPLETE;
      else
          stmt->parse_status = STMT_PARSE_COMPLETE;
-

      mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status);
      return parse;
--- 878,887 ----
Index: src/interfaces/odbc/pgtypes.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/pgtypes.c,v
retrieving revision 1.24
diff -c -r1.24 pgtypes.c
*** src/interfaces/odbc/pgtypes.c    2001/03/27 04:00:54    1.24
--- src/interfaces/odbc/pgtypes.c    2001/03/28 16:53:18
***************
*** 1,17 ****
! /* Module:            pgtypes.c
   *
   * Description:        This module contains routines for getting information
!  *                    about the supported Postgres data types.  Only the function
!  *                    pgtype_to_sqltype() returns an unknown condition.  All other
!  *                    functions return a suitable default so that even data types that
!  *                    are not directly supported can be used (it is handled as char data).
   *
   * Classes:            n/a
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 1,19 ----
! /*--------
!  * Module:            pgtypes.c
   *
   * Description:        This module contains routines for getting information
!  *                    about the supported Postgres data types.  Only the
!  *                    function pgtype_to_sqltype() returns an unknown condition.
!  *                    All other functions return a suitable default so that
!  *                    even data types that are not directly supported can be
!  *                    used (it is handled as char data).
   *
   * Classes:            n/a
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *--------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 40,54 ****

  Int4        getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);


! /* these are the types we support.    all of the pgtype_ functions should */
! /* return values for each one of these.                                    */
! /* Even types not directly supported are handled as character types
!    so all types should work (points, etc.) */

- /* ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo.  Instead, all
-    the SQL TYPES are reported and mapped to a corresponding Postgres Type
- */
  /*
  Int4 pgtypes_defined[]    = {
                  PG_TYPE_CHAR,
--- 42,59 ----

  Int4        getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);

+ /*
+  * these are the types we support.    all of the pgtype_ functions should
+  * return values for each one of these.
+  * Even types not directly supported are handled as character types
+  * so all types should work (points, etc.)
+  */

! /*
!  * ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo.  Instead, all
!  *  the SQL TYPES are reported and mapped to a corresponding Postgres Type
!  */

  /*
  Int4 pgtypes_defined[]    = {
                  PG_TYPE_CHAR,
***************
*** 109,115 ****

      switch (fSqlType)
      {
-
          case SQL_BINARY:
              pgType = PG_TYPE_BYTEA;
              break;
--- 114,119 ----
***************
*** 185,199 ****
      return pgType;
  }

! /*    There are two ways of calling this function:
!     1.    When going through the supported PG types (SQLGetTypeInfo)
!     2.    When taking any type id (SQLColumns, SQLGetData)
!
!     The first type will always work because all the types defined are returned here.
!     The second type will return a default based on global parameter when it does not
!     know.    This allows for supporting
!     types that are unknown.  All other pg routines in here return a suitable default.
! */
  Int2
  pgtype_to_sqltype(StatementClass *stmt, Int4 type)
  {
--- 189,206 ----
      return pgType;
  }

! /*
!  *    There are two ways of calling this function:
!  *
!  *    1.    When going through the supported PG types (SQLGetTypeInfo)
!  *
!  *    2.    When taking any type id (SQLColumns, SQLGetData)
!  *
!  *    The first type will always work because all the types defined are returned here.
!  *    The second type will return a default based on global parameter when it does not
!  *    know.    This allows for supporting
!  *    types that are unknown.  All other pg routines in here return a suitable default.
!  */
  Int2
  pgtype_to_sqltype(StatementClass *stmt, Int4 type)
  {
***************
*** 228,234 ****
          case PG_TYPE_INT4:
              return SQL_INTEGER;

!             /* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
          case PG_TYPE_INT8:
              return SQL_CHAR;

--- 235,241 ----
          case PG_TYPE_INT4:
              return SQL_INTEGER;

!         /* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
          case PG_TYPE_INT8:
              return SQL_CHAR;

***************
*** 253,266 ****
              return globals.bools_as_char ? SQL_CHAR : SQL_BIT;

          default:
-
              /*
               * first, check to see if 'type' is in list.  If not, look up
               * with query. Add oid, name to list.  If it's already in
               * list, just return.
               */
!             if (type == stmt->hdbc->lobj_type)    /* hack until permanent
!                                                  * type is available */
                  return SQL_LONGVARBINARY;

              return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
--- 260,272 ----
              return globals.bools_as_char ? SQL_CHAR : SQL_BIT;

          default:
              /*
               * first, check to see if 'type' is in list.  If not, look up
               * with query. Add oid, name to list.  If it's already in
               * list, just return.
               */
!             /* hack until permanent type is available */
!             if (type == stmt->hdbc->lobj_type)
                  return SQL_LONGVARBINARY;

              return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
***************
*** 305,313 ****
              return SQL_C_BINARY;

          default:
!
!             if (type == stmt->hdbc->lobj_type)    /* hack until permanent
!                                                  * type is available */
                  return SQL_C_BINARY;

              return SQL_C_CHAR;
--- 311,318 ----
              return SQL_C_BINARY;

          default:
!             /* hack until permanent type is available */
!             if (type == stmt->hdbc->lobj_type)
                  return SQL_C_BINARY;

              return SQL_C_CHAR;
***************
*** 319,325 ****
  {
      switch (type)
      {
!             case PG_TYPE_CHAR:return "char";
          case PG_TYPE_CHAR2:
              return "char2";
          case PG_TYPE_CHAR4:
--- 324,330 ----
  {
      switch (type)
      {
!         case PG_TYPE_CHAR:return "char";
          case PG_TYPE_CHAR2:
              return "char2";
          case PG_TYPE_CHAR4:
***************
*** 369,376 ****
              return PG_TYPE_LO_NAME;

          default:
!             if (type == stmt->hdbc->lobj_type)    /* hack until permanent
!                                                  * type is available */
                  return PG_TYPE_LO_NAME;

              /*
--- 374,381 ----
              return PG_TYPE_LO_NAME;

          default:
!                 /* hack until permanent type is available */
!             if (type == stmt->hdbc->lobj_type)
                  return PG_TYPE_LO_NAME;

              /*
***************
*** 524,542 ****
          return p;
  }

! /*    For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
!     override this length with the atttypmod length from pg_attribute .
!
!     If col >= 0, then will attempt to get the info from the result set.
!     This is used for functions SQLDescribeCol and SQLColAttributes.
! */
  Int4
  pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
  {
-
      switch (type)
      {
-
          case PG_TYPE_CHAR:
              return 1;
          case PG_TYPE_CHAR2:
--- 529,546 ----
          return p;
  }

! /*
!  *    For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
!  *    override this length with the atttypmod length from pg_attribute .
!  *
!  *    If col >= 0, then will attempt to get the info from the result set.
!  *    This is used for functions SQLDescribeCol and SQLColAttributes.
!  */
  Int4
  pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
  {
      switch (type)
      {
          case PG_TYPE_CHAR:
              return 1;
          case PG_TYPE_CHAR2:
***************
*** 600,606 ****
  Int4
  pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
  {
-
      switch (type)
      {
          case PG_TYPE_INT2:
--- 604,609 ----
***************
*** 628,649 ****
          case PG_TYPE_FLOAT8:
              return 22;

!             /* Character types use regular precision */
          default:
              return pgtype_precision(stmt, type, col, handle_unknown_size_as);
      }
  }

! /*    For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
!     override this length with the atttypmod length from pg_attribute
! */
  Int4
  pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
  {
-
      switch (type)
      {
-
          case PG_TYPE_INT2:
              return 2;

--- 631,651 ----
          case PG_TYPE_FLOAT8:
              return 22;

!         /* Character types use regular precision */
          default:
              return pgtype_precision(stmt, type, col, handle_unknown_size_as);
      }
  }

! /*
!  *    For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
!  *    override this length with the atttypmod length from pg_attribute
!  */
  Int4
  pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
  {
      switch (type)
      {
          case PG_TYPE_INT2:
              return 2;

***************
*** 673,681 ****
          case PG_TYPE_DATETIME:
          case PG_TYPE_TIMESTAMP:
              return 16;
-

!             /* Character types (and NUMERIC) use the default precision */
          default:
              return pgtype_precision(stmt, type, col, handle_unknown_size_as);
      }
--- 675,682 ----
          case PG_TYPE_DATETIME:
          case PG_TYPE_TIMESTAMP:
              return 16;

!         /* Character types (and NUMERIC) use the default precision */
          default:
              return pgtype_precision(stmt, type, col, handle_unknown_size_as);
      }
***************
*** 686,692 ****
  {
      switch (type)
      {
-
          case PG_TYPE_INT2:
          case PG_TYPE_OID:
          case PG_TYPE_XID:
--- 687,692 ----
***************
*** 697,706 ****
          case PG_TYPE_MONEY:
          case PG_TYPE_BOOL:

!             /*
!              * Number of digits to the right of the decimal point in
!              * "yyyy-mm=dd hh:mm:ss[.f...]"
!              */
          case PG_TYPE_ABSTIME:
          case PG_TYPE_DATETIME:
          case PG_TYPE_TIMESTAMP:
--- 697,706 ----
          case PG_TYPE_MONEY:
          case PG_TYPE_BOOL:

!         /*
!          * Number of digits to the right of the decimal point in
!          * "yyyy-mm=dd hh:mm:ss[.f...]"
!          */
          case PG_TYPE_ABSTIME:
          case PG_TYPE_DATETIME:
          case PG_TYPE_TIMESTAMP:
***************
*** 729,740 ****
          case PG_TYPE_MONEY:
          case PG_TYPE_FLOAT8:
              return 10;
-
          default:
              return -1;
      }
  }

  Int2
  pgtype_nullable(StatementClass *stmt, Int4 type)
  {
--- 729,740 ----
          case PG_TYPE_MONEY:
          case PG_TYPE_FLOAT8:
              return 10;
          default:
              return -1;
      }
  }

+
  Int2
  pgtype_nullable(StatementClass *stmt, Int4 type)
  {
***************
*** 746,752 ****
  {
      switch (type)
      {
-
          case PG_TYPE_INT2:
          case PG_TYPE_OID:
          case PG_TYPE_XID:
--- 746,751 ----
***************
*** 853,859 ****
  {
      switch (type)
      {
-
              case PG_TYPE_INT2:
              case PG_TYPE_OID:
              case PG_TYPE_XID:
--- 852,857 ----
***************
*** 874,880 ****
  {
      switch (type)
      {
-
              case PG_TYPE_INT2:
              case PG_TYPE_OID:
              case PG_TYPE_XID:
--- 872,877 ----
***************
*** 895,902 ****
  {
      switch (type)
      {
!             case PG_TYPE_CHAR:
!             case PG_TYPE_VARCHAR:return "max. length";
          default:
              return NULL;
      }
--- 892,899 ----
  {
      switch (type)
      {
!         case PG_TYPE_CHAR:
!         case PG_TYPE_VARCHAR:return "max. length";
          default:
              return NULL;
      }
***************
*** 906,913 ****
  Int2
  sqltype_to_default_ctype(Int2 sqltype)
  {
!     /* from the table on page 623 of ODBC 2.0 Programmer's Reference */
!     /* (Appendix D) */
      switch (sqltype)
      {
          case SQL_CHAR:
--- 903,912 ----
  Int2
  sqltype_to_default_ctype(Int2 sqltype)
  {
!     /*
!      *    from the table on page 623 of ODBC 2.0 Programmer's Reference
!      *     (Appendix D)
!      */
      switch (sqltype)
      {
          case SQL_CHAR:
***************
*** 951,957 ****
          case SQL_TIMESTAMP:
              return SQL_C_TIMESTAMP;

!         default:                /* should never happen */
              return SQL_C_CHAR;
      }
  }
--- 950,957 ----
          case SQL_TIMESTAMP:
              return SQL_C_TIMESTAMP;

!         default:
!             /* should never happen */
              return SQL_C_CHAR;
      }
  }
Index: src/interfaces/odbc/psqlodbc.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/psqlodbc.c,v
retrieving revision 1.15
diff -c -r1.15 psqlodbc.c
*** src/interfaces/odbc/psqlodbc.c    2001/03/27 04:00:54    1.15
--- src/interfaces/odbc/psqlodbc.c    2001/03/28 16:53:19
***************
*** 1,15 ****
! /* Module:            psqlodbc.c
   *
!  * Description:        This module contains the main entry point (DllMain) for the library.
!  *                    It also contains functions to get and set global variables for the
!  *                    driver in the registry.
   *
   * Classes:            n/a
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 1,16 ----
! /*--------
!  * Module:            psqlodbc.c
   *
!  * Description:        This module contains the main entry point (DllMain)
!  *                    for the library.  It also contains functions to get
!  *                    and set global variables for the driver in the registry.
   *
   * Classes:            n/a
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *--------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 59,65 ****
              if (LOBYTE(wsaData.wVersion) != 1 ||
                  HIBYTE(wsaData.wVersion) != 1)
              {
-
                  WSACleanup();
                  return FALSE;
              }
--- 60,65 ----
***************
*** 71,79 ****
              break;

          case DLL_PROCESS_DETACH:
-
              WSACleanup();
-
              return TRUE;

          case DLL_THREAD_DETACH:
--- 71,77 ----
***************
*** 111,117 ****

  #else                            /* not __GNUC__ */

! /* These two functions do shared library initialziation on UNIX, well at least
   * on Linux. I don't know about other systems.
   */
  BOOL
--- 109,116 ----

  #else                            /* not __GNUC__ */

! /*
!  * These two functions do shared library initialziation on UNIX, well at least
   * on Linux. I don't know about other systems.
   */
  BOOL
***************
*** 131,142 ****

  #endif     /* not WIN32 */

! /*    This function is used to cause the Driver Manager to
!     call functions by number rather than name, which is faster.
!     The ordinal value of this function must be 199 to have the
!     Driver Manager do this.  Also, the ordinal values of the
!     functions must match the value of fFunction in SQLGetFunctions()
! */
  RETCODE SQL_API
  SQLDummyOrdinal(void)
  {
--- 130,142 ----

  #endif     /* not WIN32 */

! /*
!  *    This function is used to cause the Driver Manager to
!  *    call functions by number rather than name, which is faster.
!  *    The ordinal value of this function must be 199 to have the
!  *    Driver Manager do this.  Also, the ordinal values of the
!  *    functions must match the value of fFunction in SQLGetFunctions()
!  */
  RETCODE SQL_API
  SQLDummyOrdinal(void)
  {
Index: src/interfaces/odbc/qresult.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/qresult.c,v
retrieving revision 1.21
diff -c -r1.21 qresult.c
*** src/interfaces/odbc/qresult.c    2001/03/27 04:00:55    1.21
--- src/interfaces/odbc/qresult.c    2001/03/28 16:53:19
***************
*** 1,20 ****
! /* Module:            qresult.c
   *
   * Description:        This module contains functions related to
!  *                    managing result information (i.e, fetching rows from the backend,
!  *                    managing the tuple cache, etc.) and retrieving it.
!  *                    Depending on the situation, a QResultClass will hold either data
!  *                    from the backend or a manually built result (see "qresult.h" to
!  *                    see which functions/macros are for manual or backend results.
!  *                    For manually built results, the QResultClass simply points to
!  *                    TupleList and ColumnInfo structures, which actually hold the data.
   *
   * Classes:            QResultClass (Functions prefix: "QR_")
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #include "qresult.h"
--- 1,23 ----
! /*---------
!  * Module:            qresult.c
   *
   * Description:        This module contains functions related to
!  *                    managing result information (i.e, fetching rows
!  *                    from the backend, managing the tuple cache, etc.)
!  *                    and retrieving it.  Depending on the situation, a
!  *                    QResultClass will hold either data from the backend
!  *                    or a manually built result (see "qresult.h" to
!  *                    see which functions/macros are for manual or backend
!  *                    results.  For manually built results, the
!  *                    QResultClass simply points to TupleList and
!  *                    ColumnInfo structures, which actually hold the data.
   *
   * Classes:            QResultClass (Functions prefix: "QR_")
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *---------
   */

  #include "qresult.h"
***************
*** 31,38 ****

  extern GLOBAL_VALUES globals;

! /*    Used for building a Manual Result only */
! /*    All info functions call this function to create the manual result set. */
  void
  QR_set_num_fields(QResultClass *self, int new_num_fields)
  {
--- 34,43 ----

  extern GLOBAL_VALUES globals;

! /*
!  *    Used for building a Manual Result only
!  *    All info functions call this function to create the manual result set.
!  */
  void
  QR_set_num_fields(QResultClass *self, int new_num_fields)
  {
***************
*** 70,80 ****
  {
      self->base += base_inc;
  }
-
- /************************************/
- /* CLASS QResult                    */
- /************************************/

  QResultClass *
  QR_Constructor(void)
  {
--- 75,84 ----
  {
      self->base += base_inc;
  }

+ /*
+  * CLASS QResult
+  */
  QResultClass *
  QR_Constructor(void)
  {
***************
*** 111,117 ****

          rv->cache_size = globals.fetch_max;
          rv->rowset_size = 1;
-
      }

      mylog("exit QR_Constructor\n");
--- 115,120 ----
***************
*** 127,134 ****
      if (self->manual_tuples)
          TL_Destructor(self->manual_tuples);

!     /* If conn is defined, then we may have used "backend_tuples", */
!     /* so in case we need to, free it up.  Also, close the cursor. */
      if (self->conn && self->conn->sock && CC_is_in_trans(self->conn))
          QR_close(self);            /* close the cursor if there is one */

--- 130,139 ----
      if (self->manual_tuples)
          TL_Destructor(self->manual_tuples);

!     /*
!      * If conn is defined, then we may have used "backend_tuples",
!      * so in case we need to, free it up.  Also, close the cursor.
!      */
      if (self->conn && self->conn->sock && CC_is_in_trans(self->conn))
          QR_close(self);            /* close the cursor if there is one */

***************
*** 153,159 ****
      free(self);

      mylog("QResult: exit DESTRUCTOR\n");
-
  }

  void
--- 158,163 ----
***************
*** 187,193 ****

      if (self->backend_tuples)
      {
-
          for (row = 0; row < fcount; row++)
          {
              mylog("row = %d, num_fields = %d\n", row, num_fields);
--- 191,196 ----
***************
*** 217,227 ****
  {
      int            tuple_size;

!     /* If called from send_query the first time (conn != NULL),  */
!     /* then set the inTuples state, */
!     /* and read the tuples.  If conn is NULL, */
!     /* it implies that we are being called from next_tuple(), */
!     /* like to get more rows so don't call next_tuple again! */
      if (conn != NULL)
      {
          self->conn = conn;
--- 220,232 ----
  {
      int            tuple_size;

!     /*
!      * If called from send_query the first time (conn != NULL),
!      * then set the inTuples state,
!      * and read the tuples.  If conn is NULL,
!      * it implies that we are being called from next_tuple(),
!      * like to get more rows so don't call next_tuple again!
!      */
      if (conn != NULL)
      {
          self->conn = conn;
***************
*** 242,249 ****
              self->cursor = strdup(cursor);
          }

!         /* Read the field attributes. */
!         /* $$$$ Should do some error control HERE! $$$$ */
          if (CI_read_fields(self->fields, self->conn))
          {
              self->status = PGRES_FIELDS_OK;
--- 247,257 ----
              self->cursor = strdup(cursor);
          }

!         /*
!          * Read the field attributes.
!          *
!          * $$$$ Should do some error control HERE! $$$$
!          */
          if (CI_read_fields(self->fields, self->conn))
          {
              self->status = PGRES_FIELDS_OK;
***************
*** 275,281 ****

          self->inTuples = TRUE;

-
          /* Force a read to occur in next_tuple */
          self->fcount = tuple_size + 1;
          self->fetch_count = tuple_size + 1;
--- 283,288 ----
***************
*** 285,293 ****
      }
      else
      {
!
!         /* Always have to read the field attributes. */
!         /* But we dont have to reallocate memory for them! */

          if (!CI_read_fields(NULL, self->conn))
          {
--- 292,301 ----
      }
      else
      {
!         /*
!          * Always have to read the field attributes.
!          * But we dont have to reallocate memory for them!
!          */

          if (!CI_read_fields(NULL, self->conn))
          {
***************
*** 299,306 ****
      }
  }

! /*    Close the cursor and end the transaction (if no cursors left) */
! /*    We only close cursor/end the transaction if a cursor was used. */
  int
  QR_close(QResultClass *self)
  {
--- 307,316 ----
      }
  }

! /*
!  *    Close the cursor and end the transaction (if no cursors left)
!  *    We only close cursor/end the transaction if a cursor was used.
!  */
  int
  QR_close(QResultClass *self)
  {
***************
*** 346,352 ****
              }
              QR_Destructor(res);
          }
-
      }

      return TRUE;
--- 356,361 ----
***************
*** 360,366 ****
      QResultClass *res;
      SocketClass *sock;

! /* Speed up access */
      int            fetch_count = self->fetch_count;
      int            fcount = self->fcount;
      int            fetch_size,
--- 369,375 ----
      QResultClass *res;
      SocketClass *sock;

!     /* Speed up access */
      int            fetch_count = self->fetch_count;
      int            fcount = self->fcount;
      int            fetch_size,
***************
*** 369,398 ****
      char        corrected = FALSE;
      TupleField *the_tuples = self->backend_tuples;
      static char msgbuffer[MAX_MESSAGE_LEN + 1];
!     char        cmdbuffer[MAX_MESSAGE_LEN + 1]; /* QR_set_command() dups
!                                                  * this string so dont
!                                                  * need static */
      char        fetch[128];
      QueryInfo    qi;

      if (fetch_count < fcount)
!     {                            /* return a row from cache */
          mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %d\n", fetch_count, fcount);
          self->tupleField = the_tuples + (fetch_count * self->num_fields);        /* next row */
          self->fetch_count++;
          return TRUE;
      }
      else if (self->fcount < self->cache_size)
!     {                            /* last row from cache */
          /* We are done because we didn't even get CACHE_SIZE tuples */
          mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d\n", fcount, fetch_count);
          self->tupleField = NULL;
          self->status = PGRES_END_TUPLES;
!         return -1;                /* end of tuples */
      }
      else
      {
-
          /*
           * See if we need to fetch another group of rows. We may be being
           * called from send_query(), and if so, don't send another fetch,
--- 378,408 ----
      char        corrected = FALSE;
      TupleField *the_tuples = self->backend_tuples;
      static char msgbuffer[MAX_MESSAGE_LEN + 1];
!     /* QR_set_command() dups this string so don't need static */
!     char        cmdbuffer[MAX_MESSAGE_LEN + 1];
      char        fetch[128];
      QueryInfo    qi;

      if (fetch_count < fcount)
!     {
!         /* return a row from cache */
          mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %d\n", fetch_count, fcount);
          self->tupleField = the_tuples + (fetch_count * self->num_fields);        /* next row */
          self->fetch_count++;
          return TRUE;
      }
      else if (self->fcount < self->cache_size)
!     {
!         /* last row from cache */
          /* We are done because we didn't even get CACHE_SIZE tuples */
          mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d\n", fcount, fetch_count);
          self->tupleField = NULL;
          self->status = PGRES_END_TUPLES;
!         /* end of tuples */
!         return -1;
      }
      else
      {
          /*
           * See if we need to fetch another group of rows. We may be being
           * called from send_query(), and if so, don't send another fetch,
***************
*** 402,408 ****

          if (!self->inTuples)
          {
-
              if (!globals.use_declarefetch)
              {
                  mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count);
--- 412,417 ----
***************
*** 412,419 ****
              }

              if (self->base == fcount)
!             {                    /* not a correction */
!
                  /* Determine the optimum cache size.  */
                  if (globals.fetch_max % self->rowset_size == 0)
                      fetch_size = globals.fetch_max;
--- 421,428 ----
              }

              if (self->base == fcount)
!             {
!                 /* not a correction */
                  /* Determine the optimum cache size.  */
                  if (globals.fetch_max % self->rowset_size == 0)
                      fetch_size = globals.fetch_max;
***************
*** 426,433 ****
                  self->fetch_count = 1;
              }
              else
!             {                    /* need to correct */
!
                  corrected = TRUE;

                  fetch_size = end_tuple - fcount;
--- 435,442 ----
                  self->fetch_count = 1;
              }
              else
!             {
!                 /* need to correct */
                  corrected = TRUE;

                  fetch_size = end_tuple - fcount;
***************
*** 436,445 ****

                  offset = self->fetch_count;
                  self->fetch_count++;
-
              }

-
              self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField)
*self->cache_size); 
              if (!self->backend_tuples)
              {
--- 445,452 ----
***************
*** 483,499 ****
          self->fcount = 0;
      }

-
      sock = CC_get_socket(self->conn);
      self->tupleField = NULL;

      for (;;)
      {
-
          id = SOCK_get_char(sock);

          switch (id)
          {
              case 'T':            /* Tuples within tuples cannot be handled */
                  self->status = PGRES_BAD_RESPONSE;
                  QR_set_message(self, "Tuples within tuples cannot be handled");
--- 490,505 ----
          self->fcount = 0;
      }

      sock = CC_get_socket(self->conn);
      self->tupleField = NULL;

      for (;;)
      {
          id = SOCK_get_char(sock);

          switch (id)
          {
+
              case 'T':            /* Tuples within tuples cannot be handled */
                  self->status = PGRES_BAD_RESPONSE;
                  QR_set_message(self, "Tuples within tuples cannot be handled");
***************
*** 522,532 ****
                      QR_set_message(self, "Error reading the tuple");
                      return FALSE;
                  }
-
                  self->fcount++;
                  break;            /* continue reading */

-
              case 'C':            /* End of tuple list */
                  SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN);
                  QR_set_command(self, cmdbuffer);
--- 528,536 ----
***************
*** 536,542 ****
                  self->inTuples = FALSE;
                  if (self->fcount > 0)
                  {
-
                      qlog("    [ fetched %d rows ]\n", self->fcount);
                      mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->fcount);

--- 540,545 ----
***************
*** 545,552 ****
                      return TRUE;
                  }
                  else
!                 {                /* We are surely done here (we read 0
!                                  * tuples) */
                      qlog("    [ fetched 0 rows ]\n");
                      mylog("_next_tuple: 'C': DONE (fcount == 0)\n");
                      return -1;    /* end of tuples */
--- 548,555 ----
                      return TRUE;
                  }
                  else
!                 {
!                     /* We are surely done here (we read 0 tuples) */
                      qlog("    [ fetched 0 rows ]\n");
                      mylog("_next_tuple: 'C': DONE (fcount == 0)\n");
                      return -1;    /* end of tuples */
***************
*** 600,606 ****
      SocketClass *sock = CC_get_socket(self->conn);
      ColumnInfoClass *flds;

-
      /* set the current row to read the fields into */
      this_tuplefield = self->backend_tuples + (self->fcount * num_fields);

--- 603,608 ----
***************
*** 629,635 ****
          }
          else
          {
-
              /*
               * NO, the field is not null. so get at first the length of
               * the field (four bytes)
--- 631,636 ----
Index: src/interfaces/odbc/results.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/results.c,v
retrieving revision 1.27
diff -c -r1.27 results.c
*** src/interfaces/odbc/results.c    2001/03/27 04:00:55    1.27
--- src/interfaces/odbc/results.c    2001/03/28 16:53:20
***************
*** 1,17 ****
! /* Module:            results.c
   *
   * Description:        This module contains functions related to
   *                    retrieving result information through the ODBC API.
   *
   * Classes:            n/a
   *
!  * API functions:    SQLRowCount, SQLNumResultCols, SQLDescribeCol, SQLColAttributes,
!  *                    SQLGetData, SQLFetch, SQLExtendedFetch,
   *                    SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI),
   *                    SQLSetCursorName, SQLGetCursorName
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 1,18 ----
! /*-------
!  * Module:            results.c
   *
   * Description:        This module contains functions related to
   *                    retrieving result information through the ODBC API.
   *
   * Classes:            n/a
   *
!  * API functions:    SQLRowCount, SQLNumResultCols, SQLDescribeCol,
!  *                    SQLColAttributes, SQLGetData, SQLFetch, SQLExtendedFetch,
   *                    SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI),
   *                    SQLSetCursorName, SQLGetCursorName
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 42,48 ****
  extern GLOBAL_VALUES globals;


-
  RETCODE SQL_API
  SQLRowCount(
              HSTMT hstmt,
--- 43,48 ----
***************
*** 81,87 ****
      }
      else
      {
-
          res = SC_get_Result(stmt);
          if (res && pcrow)
          {
--- 81,86 ----
***************
*** 97,103 ****
              else
              {
                  *pcrow = -1;
-
                  mylog("**** SQLRowCount(): NO ROWS: *pcrow = %d\n", *pcrow);
              }

--- 96,101 ----
***************
*** 110,117 ****
  }


! /*        This returns the number of columns associated with the database */
! /*        attached to "hstmt". */


  RETCODE SQL_API
--- 108,117 ----
  }


! /*
!  *    This returns the number of columns associated with the database
!  *    attached to "hstmt".
!  */


  RETCODE SQL_API
***************
*** 135,141 ****
      parse_ok = FALSE;
      if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
      {
-
          if (stmt->parse_status == STMT_PARSE_NONE)
          {
              mylog("SQLNumResultCols: calling parse_statement on stmt=%u\n", stmt);
--- 135,140 ----
***************
*** 152,158 ****

      if (!parse_ok)
      {
-
          SC_pre_execute(stmt);
          result = SC_get_Result(stmt);

--- 151,156 ----
***************
*** 172,184 ****
      return SQL_SUCCESS;
  }

-
- /*        -        -        -        -        -        -        -        -        - */
-

!
! /*        Return information about the database column the user wants */
! /*        information about. */
  RETCODE SQL_API
  SQLDescribeCol(
                 HSTMT hstmt,
--- 170,180 ----
      return SQL_SUCCESS;
  }


! /*
!  *    Return information about the database column the user wants
!  *    information about.
!  */
  RETCODE SQL_API
  SQLDescribeCol(
                 HSTMT hstmt,
***************
*** 205,211 ****
      int            len = 0;
      RETCODE        result;

-
      mylog("%s: entering...\n", func);

      if (!stmt)
--- 201,206 ----
***************
*** 219,247 ****
      SC_clear_error(stmt);

      /*
!      * Dont check for bookmark column.    This is the responsibility of the
!      * driver manager.
       */

      icol--;                        /* use zero based column numbers */

-
      parse_ok = FALSE;
      if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
      {
-
          if (stmt->parse_status == STMT_PARSE_NONE)
          {
              mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt);
              parse_statement(stmt);
          }

-
          mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld,
stmt->fi);

          if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
          {
-
              if (icol >= stmt->nfld)
              {
                  stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
--- 214,238 ----
      SC_clear_error(stmt);

      /*
!      *    Dont check for bookmark column.    This is the responsibility of the
!      *    driver manager.
       */

      icol--;                        /* use zero based column numbers */

      parse_ok = FALSE;
      if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
      {
          if (stmt->parse_status == STMT_PARSE_NONE)
          {
              mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt);
              parse_statement(stmt);
          }

          mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld,
stmt->fi);

          if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
          {
              if (icol >= stmt->nfld)
              {
                  stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
***************
*** 261,271 ****
          }
      }

-
      /*
!      * If couldn't parse it OR the field being described was not parsed
!      * (i.e., because it was a function or expression, etc, then do it the
!      * old fashioned way.
       */
      if (!parse_ok)
      {
--- 252,261 ----
          }
      }

      /*
!      *    If couldn't parse it OR the field being described was not parsed
!      *    (i.e., because it was a function or expression, etc, then do it the
!      *    old fashioned way.
       */
      if (!parse_ok)
      {
***************
*** 295,314 ****
          col_name = QR_get_fieldname(res, icol);
          fieldtype = QR_get_field_type(res, icol);

!         precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes);        /* atoi(ci->unknown_sizes
!                                                                                          * ) */
!     }

      mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
      mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);
      mylog("describeCol: col %d precision = %d\n", icol, precision);

-
      result = SQL_SUCCESS;

!     /************************/
!     /* COLUMN NAME       */
!     /************************/
      len = strlen(col_name);

      if (pcbColName)
--- 285,303 ----
          col_name = QR_get_fieldname(res, icol);
          fieldtype = QR_get_field_type(res, icol);

!         /* atoi(ci->unknown_sizes) */
!         precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes);
!      }

      mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
      mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);
      mylog("describeCol: col %d precision = %d\n", icol, precision);

      result = SQL_SUCCESS;

!     /*
!      * COLUMN NAME
!      */
      len = strlen(col_name);

      if (pcbColName)
***************
*** 325,335 ****
              stmt->errormsg = "The buffer was too small for the result.";
          }
      }
-

!     /************************/
!     /* SQL TYPE           */
!     /************************/
      if (pfSqlType)
      {
          *pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
--- 314,323 ----
              stmt->errormsg = "The buffer was too small for the result.";
          }
      }

!     /*
!      * SQL TYPE
!      */
      if (pfSqlType)
      {
          *pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
***************
*** 337,348 ****
          mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
      }

!     /************************/
!     /* PRECISION       */
!     /************************/
      if (pcbColDef)
      {
-
          if (precision < 0)
              precision = 0;        /* "I dont know" */

--- 325,335 ----
          mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
      }

!     /*
!      * PRECISION
!      */
      if (pcbColDef)
      {
          if (precision < 0)
              precision = 0;        /* "I dont know" */

***************
*** 351,359 ****
          mylog("describeCol: col %d  *pcbColDef = %d\n", icol, *pcbColDef);
      }

!     /************************/
!     /* SCALE           */
!     /************************/
      if (pibScale)
      {
          Int2        scale;
--- 338,346 ----
          mylog("describeCol: col %d  *pcbColDef = %d\n", icol, *pcbColDef);
      }

!     /*
!      * SCALE
!      */
      if (pibScale)
      {
          Int2        scale;
***************
*** 366,374 ****
          mylog("describeCol: col %d  *pibScale = %d\n", icol, *pibScale);
      }

!     /************************/
!     /* NULLABILITY       */
!     /************************/
      if (pfNullable)
      {
          *pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype);
--- 353,361 ----
          mylog("describeCol: col %d  *pibScale = %d\n", icol, *pibScale);
      }

!     /*
!      * NULLABILITY
!      */
      if (pfNullable)
      {
          *pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype);
***************
*** 421,436 ****

      icol--;

!     unknown_sizes = globals.unknown_sizes;        /* atoi(ci->unknown_sizes);
!                                                  * */
!     if (unknown_sizes == UNKNOWNS_AS_DONTKNOW)    /* not appropriate for
!                                                  * SQLColAttributes() */
          unknown_sizes = UNKNOWNS_AS_MAX;

      parse_ok = FALSE;
      if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
      {
-
          if (stmt->parse_status == STMT_PARSE_NONE)
          {
              mylog("SQLColAttributes: calling parse_statement\n");
--- 408,423 ----

      icol--;

!     /* atoi(ci->unknown_sizes); */
!     unknown_sizes = globals.unknown_sizes;
!
!     /* not appropriate for SQLColAttributes() */
!     if (unknown_sizes == UNKNOWNS_AS_DONTKNOW)
          unknown_sizes = UNKNOWNS_AS_MAX;

      parse_ok = FALSE;
      if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
      {
          if (stmt->parse_status == STMT_PARSE_NONE)
          {
              mylog("SQLColAttributes: calling parse_statement\n");
***************
*** 453,459 ****

          if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
          {
-
              if (icol >= cols)
              {
                  stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
--- 440,445 ----
***************
*** 461,467 ****
                  SC_log_error(func, "", stmt);
                  return SQL_ERROR;
              }
-
              field_type = stmt->fi[icol]->type;
              if (field_type > 0)
                  parse_ok = TRUE;
--- 447,452 ----
***************
*** 521,533 ****
          case SQL_COLUMN_CASE_SENSITIVE:
              value = pgtype_case_sensitive(stmt, field_type);
              break;
-
-             /*
-              * This special case is handled above.
-              *
-              * case SQL_COLUMN_COUNT:
-              */

          case SQL_COLUMN_DISPLAY_SIZE:
              value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol,
unknown_sizes);

--- 506,517 ----
          case SQL_COLUMN_CASE_SENSITIVE:
              value = pgtype_case_sensitive(stmt, field_type);
              break;

+         /*
+          * This special case is handled above.
+          *
+          * case SQL_COLUMN_COUNT:
+          */
          case SQL_COLUMN_DISPLAY_SIZE:
              value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol,
unknown_sizes);

***************
*** 543,553 ****
                  mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p);
                  break;

!             }                    /* otherwise same as column name -- FALL
!                                  * THROUGH!!! */

          case SQL_COLUMN_NAME:
-
              p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol);

              mylog("SQLColAttr: COLUMN_NAME = '%s'\n", p);
--- 527,536 ----
                  mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p);
                  break;

!             }
!             /* otherwise same as column name -- FALL THROUGH!!! */

          case SQL_COLUMN_NAME:
              p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol);

              mylog("SQLColAttr: COLUMN_NAME = '%s'\n", p);
***************
*** 590,596 ****
              break;

          case SQL_COLUMN_TABLE_NAME:
-
              p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : "";

              mylog("SQLColAttr: TABLE_NAME = '%s'\n", p);
--- 573,578 ----
***************
*** 612,625 ****
              break;

          case SQL_COLUMN_UPDATABLE:
-
              /*
               * Neither Access or Borland care about this.
               *
               * if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY;
               * else
               */
-
              value = SQL_ATTR_WRITE;

              mylog("SQLColAttr: UPDATEABLE = %d\n", value);
--- 594,605 ----
***************
*** 648,665 ****
              *pcbDesc = len;
      }
      else
!     {                            /* numeric data */
!
          if (pfDesc)
              *pfDesc = value;
-
      }

-
      return result;
  }

! /*        Returns result data for a single column in the current row. */

  RETCODE SQL_API
  SQLGetData(
--- 628,643 ----
              *pcbDesc = len;
      }
      else
!     {
!         /* numeric data */
          if (pfDesc)
              *pfDesc = value;
      }

      return result;
  }

! /*    Returns result data for a single column in the current row. */

  RETCODE SQL_API
  SQLGetData(
***************
*** 707,713 ****

      if (icol == 0)
      {
-
          if (stmt->options.use_bookmarks == SQL_UB_OFF)
          {
              stmt->errornumber = STMT_COLNUM_ERROR;
--- 685,690 ----
***************
*** 726,737 ****
          }

          get_bookmark = TRUE;
-
      }
-
      else
      {
-
          /* use zero-based column numbers */
          icol--;

--- 703,711 ----
***************
*** 770,776 ****
          }
      }
      else
!     {                            /* it's a SOCKET result (backend data) */
          if (stmt->currTuple == -1 || !res || !res->tupleField)
          {
              stmt->errormsg = "Not positioned on a valid row for GetData.";
--- 744,751 ----
          }
      }
      else
!     {
!         /* it's a SOCKET result (backend data) */
          if (stmt->currTuple == -1 || !res || !res->tupleField)
          {
              stmt->errormsg = "Not positioned on a valid row for GetData.";
***************
*** 844,854 ****
      }
  }

-

! /*        Returns data for bound columns in the current row ("hstmt->iCursor"), */
! /*        advances the cursor. */
!
  RETCODE SQL_API
  SQLFetch(
           HSTMT hstmt)
--- 819,829 ----
      }
  }


! /*
!  *        Returns data for bound columns in the current row ("hstmt->iCursor"),
!  *        advances the cursor.
!  */
  RETCODE SQL_API
  SQLFetch(
           HSTMT hstmt)
***************
*** 892,898 ****
          return SQL_ERROR;
      }

-
      if (stmt->status != STMT_FINISHED)
      {
          stmt->errornumber = STMT_STATUS_ERROR;
--- 867,872 ----
***************
*** 917,924 ****
      return SC_fetch(stmt);
  }

! /*        This fetchs a block of data (rowset). */
!
  RETCODE SQL_API
  SQLExtendedFetch(
                   HSTMT hstmt,
--- 891,897 ----
      return SC_fetch(stmt);
  }

! /*    This fetchs a block of data (rowset). */
  RETCODE SQL_API
  SQLExtendedFetch(
                   HSTMT hstmt,
***************
*** 1020,1026 ****
      switch (fFetchType)
      {
          case SQL_FETCH_NEXT:
-
              /*
               * From the odbc spec... If positioned before the start of the
               * RESULT SET, then this should be equivalent to
--- 993,998 ----
***************
*** 1031,1066 ****
                  stmt->rowset_start = 0;

              else
-             {
-
                  stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : stmt->options.rowset_size);
-             }

              mylog("SQL_FETCH_NEXT: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
              break;

          case SQL_FETCH_PRIOR:
              mylog("SQL_FETCH_PRIOR: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
-
-
              /*
               * From the odbc spec... If positioned after the end of the
               * RESULT SET, then this should be equivalent to
               * SQL_FETCH_LAST.
               */
-
              if (stmt->rowset_start >= num_tuples)
              {
                  stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size);

              }
              else
-             {
-
                  stmt->rowset_start -= stmt->options.rowset_size;
-
-             }
-
              break;

          case SQL_FETCH_FIRST:
--- 1003,1027 ----
***************
*** 1091,1101 ****
              /* Position with respect to the end of the result set */
              else
                  stmt->rowset_start = num_tuples + irow;
-
              break;

          case SQL_FETCH_RELATIVE:
-
              /*
               * Refresh the current rowset -- not currently implemented,
               * but lie anyway
--- 1052,1060 ----
***************
*** 1104,1128 ****
                  break;

              stmt->rowset_start += irow;
-
-
              break;

          case SQL_FETCH_BOOKMARK:
-
              stmt->rowset_start = irow - 1;
              break;

          default:
              SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt);
              return SQL_ERROR;
-
      }

!
!     /***********************************/
!     /* CHECK FOR PROPER CURSOR STATE  */
!     /***********************************/

      /*
       * Handle Declare Fetch style specially because the end is not really
--- 1063,1082 ----
                  break;

              stmt->rowset_start += irow;
              break;

          case SQL_FETCH_BOOKMARK:
              stmt->rowset_start = irow - 1;
              break;

          default:
              SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt);
              return SQL_ERROR;
      }

!     /*
!      * CHECK FOR PROPER CURSOR STATE
!      */

      /*
       * Handle Declare Fetch style specially because the end is not really
***************
*** 1172,1178 ****
      truncated = error = FALSE;
      for (i = 0; i < stmt->options.rowset_size; i++)
      {
-
          stmt->bind_row = i;        /* set the binding location */
          result = SC_fetch(stmt);

--- 1126,1131 ----
***************
*** 1212,1232 ****
          *pcrow = i;

      if (i == 0)
!         return SQL_NO_DATA_FOUND;        /* Only DeclareFetch should wind
!                                          * up here */
      else if (error)
          return SQL_ERROR;
      else if (truncated)
          return SQL_SUCCESS_WITH_INFO;
      else
          return SQL_SUCCESS;
-
  }

-
- /*        This determines whether there are more results sets available for */
- /*        the "hstmt". */

  /* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */
  RETCODE SQL_API
  SQLMoreResults(
--- 1165,1185 ----
          *pcrow = i;

      if (i == 0)
!         /* Only DeclareFetch should wind up here */
!         return SQL_NO_DATA_FOUND;
      else if (error)
          return SQL_ERROR;
      else if (truncated)
          return SQL_SUCCESS_WITH_INFO;
      else
          return SQL_SUCCESS;
  }


+ /*
+  *        This determines whether there are more results sets available for
+  *        the "hstmt".
+  */
  /* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */
  RETCODE SQL_API
  SQLMoreResults(
***************
*** 1235,1242 ****
      return SQL_NO_DATA_FOUND;
  }

! /*       This positions the cursor within a rowset, that was positioned using SQLExtendedFetch. */
! /*       This will be useful (so far) only when using SQLGetData after SQLExtendedFetch.     */
  RETCODE SQL_API
  SQLSetPos(
            HSTMT hstmt,
--- 1188,1197 ----
      return SQL_NO_DATA_FOUND;
  }

! /*
!  *    This positions the cursor within a rowset, that was positioned using SQLExtendedFetch.
!  *    This will be useful (so far) only when using SQLGetData after SQLExtendedFetch.
!  */
  RETCODE SQL_API
  SQLSetPos(
            HSTMT hstmt,
***************
*** 1301,1311 ****
      stmt->currTuple = stmt->rowset_start + irow;

      return SQL_SUCCESS;
-
  }

  /*        Sets options that control the behavior of cursors. */
-
  RETCODE SQL_API
  SQLSetScrollOptions(
                      HSTMT hstmt,
--- 1256,1264 ----
***************
*** 1319,1327 ****
      return SQL_ERROR;
  }

-
- /*        Set the cursor name on a statement handle */

  RETCODE SQL_API
  SQLSetCursorName(
                   HSTMT hstmt,
--- 1272,1279 ----
      return SQL_ERROR;
  }


+ /*    Set the cursor name on a statement handle */
  RETCODE SQL_API
  SQLSetCursorName(
                   HSTMT hstmt,
***************
*** 1354,1361 ****
      return SQL_SUCCESS;
  }

- /*        Return the cursor name for a statement handle */

  RETCODE SQL_API
  SQLGetCursorName(
                   HSTMT hstmt,
--- 1306,1313 ----
      return SQL_SUCCESS;
  }


+ /*    Return the cursor name for a statement handle */
  RETCODE SQL_API
  SQLGetCursorName(
                   HSTMT hstmt,
Index: src/interfaces/odbc/setup.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/setup.c,v
retrieving revision 1.17
diff -c -r1.17 setup.c
*** src/interfaces/odbc/setup.c    2001/03/27 04:00:55    1.17
--- src/interfaces/odbc/setup.c    2001/03/28 16:53:22
***************
*** 1,4 ****
! /* Module:            setup.c
   *
   * Description:        This module contains the setup functions for
   *                    adding/modifying a Data Source in the ODBC.INI portion
--- 1,5 ----
! /*-------
!  * Module:            setup.c
   *
   * Description:        This module contains the setup functions for
   *                    adding/modifying a Data Source in the ODBC.INI portion
***************
*** 9,15 ****
   * API functions:    ConfigDSN
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #include  "psqlodbc.h"
--- 10,16 ----
   * API functions:    ConfigDSN
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #include  "psqlodbc.h"
***************
*** 28,34 ****
  extern HINSTANCE NEAR s_hModule;/* Saved module handle. */
  extern GLOBAL_VALUES globals;

! /* Constants --------------------------------------------------------------- */
  #define MIN(x,y)      ((x) < (y) ? (x) : (y))

  #ifdef WIN32
--- 29,35 ----
  extern HINSTANCE NEAR s_hModule;/* Saved module handle. */
  extern GLOBAL_VALUES globals;

! /* Constants */
  #define MIN(x,y)      ((x) < (y) ? (x) : (y))

  #ifdef WIN32
***************
*** 40,46 ****
  #define MAXDSNAME        (32+1)    /* Max data source name length */


! /* Globals ----------------------------------------------------------------- */
  /* NOTE:  All these are used by the dialog procedures */
  typedef struct tagSETUPDLG
  {
--- 41,47 ----
  #define MAXDSNAME        (32+1)    /* Max data source name length */


! /* Globals */
  /* NOTE:  All these are used by the dialog procedures */
  typedef struct tagSETUPDLG
  {
***************
*** 55,77 ****



! /* Prototypes -------------------------------------------------------------- */
  void INTFUNC CenterDialog(HWND hdlg);
  int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam);
  void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg);
  BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);


! /* ConfigDSN ---------------------------------------------------------------
!   Description:    ODBC Setup entry point
!                 This entry point is called by the ODBC Installer
!                 (see file header for more details)
!   Input         :    hwnd ----------- Parent window handle
!                 fRequest ------- Request type (i.e., add, config, or remove)
!                 lpszDriver ----- Driver name
!                 lpszAttributes - data source attribute string
!   Output     :    TRUE success, FALSE otherwise
! --------------------------------------------------------------------------*/

  BOOL        CALLBACK
  ConfigDSN(HWND hwnd,
--- 56,81 ----



! /* Prototypes */
  void INTFUNC CenterDialog(HWND hdlg);
  int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam);
  void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg);
  BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);


! /*--------
!  *    ConfigDSN
!  *
!  *  Description:    ODBC Setup entry point
!  *                This entry point is called by the ODBC Installer
!  *                (see file header for more details)
!  *  Input     :    hwnd ----------- Parent window handle
!  *                fRequest ------- Request type (i.e., add, config, or remove)
!  *                lpszDriver ----- Driver name
!  *                lpszAttributes - data source attribute string
!  *  Output     :    TRUE success, FALSE otherwise
!  *--------
!  */

  BOOL        CALLBACK
  ConfigDSN(HWND hwnd,
***************
*** 111,117 ****
          else
              fSuccess = SQLRemoveDSNFromIni(lpsetupdlg->ci.dsn);
      }
-
      /* Add or Configure data source */
      else
      {
--- 115,120 ----
***************
*** 134,140 ****
                                                 ConfigDlgProc,
                                               (LONG) (LPSTR) lpsetupdlg));
          }
-
          else if (lpsetupdlg->ci.dsn[0])
              fSuccess = SetDSNAttributes(hwnd, lpsetupdlg);
          else
--- 137,142 ----
***************
*** 148,158 ****
  }


! /* CenterDialog ------------------------------------------------------------
!         Description:  Center the dialog over the frame window
!         Input       :  hdlg -- Dialog window handle
!         Output       :  None
! --------------------------------------------------------------------------*/
  void        INTFUNC
  CenterDialog(HWND hdlg)
  {
--- 150,163 ----
  }


! /*-------
!  * CenterDialog
!  *
!  *        Description:  Center the dialog over the frame window
!  *        Input       :  hdlg -- Dialog window handle
!  *        Output       :  None
!  *-------
!  */
  void        INTFUNC
  CenterDialog(HWND hdlg)
  {
***************
*** 197,220 ****
      MoveWindow(hdlg, rcDlg.left, rcDlg.top, cx, cy, TRUE);
      return;
  }
-
- /* ConfigDlgProc -----------------------------------------------------------
-   Description:    Manage add data source name dialog
-   Input         :    hdlg --- Dialog window handle
-                 wMsg --- Message
-                 wParam - Message parameter
-                 lParam - Message parameter
-   Output     :    TRUE if message processed, FALSE otherwise
- --------------------------------------------------------------------------*/

!
  int            CALLBACK
  ConfigDlgProc(HWND hdlg,
                WORD wMsg,
                WPARAM wParam,
                LPARAM lParam)
  {
-
      switch (wMsg)
      {
              /* Initialize the dialog */
--- 202,224 ----
      MoveWindow(hdlg, rcDlg.left, rcDlg.top, cx, cy, TRUE);
      return;
  }

! /*-------
!  * ConfigDlgProc
!  *  Description:    Manage add data source name dialog
!  *  Input     :    hdlg --- Dialog window handle
!  *                wMsg --- Message
!  *                wParam - Message parameter
!  *                lParam - Message parameter
!  *  Output     :    TRUE if message processed, FALSE otherwise
!  *-------
!  */
  int            CALLBACK
  ConfigDlgProc(HWND hdlg,
                WORD wMsg,
                WPARAM wParam,
                LPARAM lParam)
  {
      switch (wMsg)
      {
              /* Initialize the dialog */
***************
*** 241,251 ****
                  /* Fill in any defaults */
                  getDSNdefaults(ci);

-
                  /* Initialize dialog fields */
                  SetDlgStuff(hdlg, ci);

-
                  if (lpsetupdlg->fDefault)
                  {
                      EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
--- 245,253 ----
***************
*** 259,272 ****
                                 EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L);
                  return TRUE;    /* Focus was not set */
              }
-

!             /* Process buttons */
          case WM_COMMAND:
-
              switch (GET_WM_COMMAND_ID(wParam, lParam))
              {
-
                      /*
                       * Ensure the OK button is enabled only when a data
                       * source name
--- 261,271 ----
                                 EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L);
                  return TRUE;    /* Focus was not set */
              }

!         /* Process buttons */
          case WM_COMMAND:
              switch (GET_WM_COMMAND_ID(wParam, lParam))
              {
                      /*
                       * Ensure the OK button is enabled only when a data
                       * source name
***************
*** 281,292 ****
                          EnableWindow(GetDlgItem(hdlg, IDOK),
                                       GetDlgItemText(hdlg, IDC_DSNAME,
                                                  szItem, sizeof(szItem)));
-
                          return TRUE;
                      }
                      break;

!                     /* Accept results */
                  case IDOK:
                      {
                          LPSETUPDLG    lpsetupdlg;
--- 280,290 ----
                          EnableWindow(GetDlgItem(hdlg, IDOK),
                                       GetDlgItemText(hdlg, IDC_DSNAME,
                                                  szItem, sizeof(szItem)));
                          return TRUE;
                      }
                      break;

!                 /* Accept results */
                  case IDOK:
                      {
                          LPSETUPDLG    lpsetupdlg;
***************
*** 297,304 ****
                              GetDlgItemText(hdlg, IDC_DSNAME,
                                             lpsetupdlg->ci.dsn,
                                             sizeof(lpsetupdlg->ci.dsn));
-
-
                          /* Get Dialog Values */
                          GetDlgStuff(hdlg, &lpsetupdlg->ci);

--- 295,300 ----
***************
*** 306,318 ****
                          SetDSNAttributes(hdlg, lpsetupdlg);
                      }

!                     /* Return to caller */
                  case IDCANCEL:
                      EndDialog(hdlg, wParam);
                      return TRUE;

                  case IDC_DRIVER:
-
                      DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
                                  hdlg, driver_optionsProc, (LPARAM) NULL);

--- 302,313 ----
                          SetDSNAttributes(hdlg, lpsetupdlg);
                      }

!                 /* Return to caller */
                  case IDCANCEL:
                      EndDialog(hdlg, wParam);
                      return TRUE;

                  case IDC_DRIVER:
                      DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
                                  hdlg, driver_optionsProc, (LPARAM) NULL);

***************
*** 330,336 ****
                          return TRUE;
                      }
              }
-
              break;
      }

--- 325,330 ----
***************
*** 339,349 ****
  }


! /* ParseAttributes ---------------------------------------------------------
!   Description:    Parse attribute string moving values into the aAttr array
!   Input         :    lpszAttributes - Pointer to attribute string
!   Output     :    None (global aAttr normally updated)
! --------------------------------------------------------------------------*/
  void        INTFUNC
  ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
  {
--- 333,346 ----
  }


! /*-------
!  * ParseAttributes
!  *
!  *  Description:    Parse attribute string moving values into the aAttr array
!  *  Input     :    lpszAttributes - Pointer to attribute string
!  *  Output     :    None (global aAttr normally updated)
!  *-------
!  */
  void        INTFUNC
  ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
  {
***************
*** 356,363 ****
      memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo));

      for (lpsz = lpszAttributes; *lpsz; lpsz++)
!     {                            /* Extract key name (e.g., DSN), it must
!                                  * be terminated by an equals */
          lpszStart = lpsz;
          for (;; lpsz++)
          {
--- 353,360 ----
      memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo));

      for (lpsz = lpszAttributes; *lpsz; lpsz++)
!     {
!         /* Extract key name (e.g., DSN), it must be terminated by an equals */
          lpszStart = lpsz;
          for (;; lpsz++)
          {
***************
*** 370,384 ****
          cbKey = lpsz - lpszStart;
          if (cbKey < sizeof(aszKey))
          {
-
              _fmemcpy(aszKey, lpszStart, cbKey);
              aszKey[cbKey] = '\0';
          }

          /* Locate end of key value */
          lpszStart = ++lpsz;
!         for (; *lpsz; lpsz++);
!

          /* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */
          _fmemcpy(value, lpszStart, MIN(lpsz - lpszStart + 1, MAXPGPATH));
--- 367,380 ----
          cbKey = lpsz - lpszStart;
          if (cbKey < sizeof(aszKey))
          {
              _fmemcpy(aszKey, lpszStart, cbKey);
              aszKey[cbKey] = '\0';
          }

          /* Locate end of key value */
          lpszStart = ++lpsz;
!         for (; *lpsz; lpsz++)
!             ;

          /* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */
          _fmemcpy(value, lpszStart, MIN(lpsz - lpszStart + 1, MAXPGPATH));
***************
*** 392,403 ****
  }


! /* SetDSNAttributes --------------------------------------------------------
!   Description:    Write data source attributes to ODBC.INI
!   Input         :    hwnd - Parent window handle (plus globals)
!   Output     :    TRUE if successful, FALSE otherwise
! --------------------------------------------------------------------------*/
!
  BOOL        INTFUNC
  SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
  {
--- 388,401 ----
  }


! /*--------
!  * SetDSNAttributes
!  *
!  *  Description:    Write data source attributes to ODBC.INI
!  *  Input     :    hwnd - Parent window handle (plus globals)
!  *  Output     :    TRUE if successful, FALSE otherwise
!  *--------
!  */
  BOOL        INTFUNC
  SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
  {
***************
*** 425,434 ****
          return FALSE;
      }

-
      /* Update ODBC.INI */
      writeDSNinfo(&lpsetupdlg->ci);
-

      /* If the data source name has changed, remove the old name */
      if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn))
--- 423,430 ----
Index: src/interfaces/odbc/socket.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/socket.c,v
retrieving revision 1.22
diff -c -r1.22 socket.c
*** src/interfaces/odbc/socket.c    2001/03/27 04:00:55    1.22
--- src/interfaces/odbc/socket.c    2001/03/28 16:53:22
***************
*** 1,4 ****
! /* Module:            socket.c
   *
   * Description:        This module contains functions for low level socket
   *                    operations (connecting/reading/writing to the backend)
--- 1,5 ----
! /*-------
!  * Module:            socket.c
   *
   * Description:        This module contains functions for low level socket
   *                    operations (connecting/reading/writing to the backend)
***************
*** 8,14 ****
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 9,15 ----
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 70,83 ****
              free(rv);
              return NULL;
          }
-
          rv->errormsg = NULL;
          rv->errornumber = 0;
-
          rv->reverse = FALSE;
      }
      return rv;
-
  }

  void
--- 71,81 ----
***************
*** 97,103 ****
          free(self->buffer_out);

      free(self);
-
  }


--- 95,100 ----
***************
*** 149,155 ****
      if (connect(self->socket, (struct sockaddr *) & (sadr),
                  sizeof(sadr)) < 0)
      {
-
          self->errornumber = SOCKET_COULD_NOT_CONNECT;
          self->errormsg = "Could not connect to remote socket.";
          closesocket(self->socket);
--- 146,151 ----
***************
*** 194,202 ****
  }


! /*    bufsize must include room for the null terminator
!     will read at most bufsize-1 characters + null.
! */
  void
  SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
  {
--- 190,199 ----
  }


! /*
!  *    bufsize must include room for the null terminator
!  *    will read at most bufsize-1 characters + null.
!  */
  void
  SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
  {
***************
*** 300,311 ****
  unsigned char
  SOCK_get_next_byte(SocketClass *self)
  {
-
      if (self->buffer_read_in >= self->buffer_filled_in)
      {
!         /* there are no more bytes left in the buffer so */
!         /* reload the buffer */
!
          self->buffer_read_in = 0;
          self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0);

--- 297,308 ----
  unsigned char
  SOCK_get_next_byte(SocketClass *self)
  {
      if (self->buffer_read_in >= self->buffer_filled_in)
      {
!         /*
!          * there are no more bytes left in the buffer so
!          * reload the buffer
!          */
          self->buffer_read_in = 0;
          self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0);

Index: src/interfaces/odbc/statement.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/statement.c,v
retrieving revision 1.35
diff -c -r1.35 statement.c
*** src/interfaces/odbc/statement.c    2001/03/27 04:00:55    1.35
--- src/interfaces/odbc/statement.c    2001/03/28 16:53:22
***************
*** 1,4 ****
! /* Module:            statement.c
   *
   * Description:        This module contains functions related to creating
   *                    and manipulating a statement.
--- 1,5 ----
! /*-------
!  * Module:            statement.c
   *
   * Description:        This module contains functions related to creating
   *                    and manipulating a statement.
***************
*** 8,14 ****
   * API functions:    SQLAllocStmt, SQLFreeStmt
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #ifdef HAVE_CONFIG_H
--- 9,15 ----
   * API functions:    SQLAllocStmt, SQLFreeStmt
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #ifdef HAVE_CONFIG_H
***************
*** 126,137 ****

      *phstmt = (HSTMT) stmt;

!     /*
!      * Copy default statement options based from Connection options
!      */
      stmt->options = conn->stmtOptions;

-
      /* Save the handle for later */
      stmt->phstmt = phstmt;

--- 127,135 ----

      *phstmt = (HSTMT) stmt;

!     /* Copy default statement options based from Connection options */
      stmt->options = conn->stmtOptions;

      /* Save the handle for later */
      stmt->phstmt = phstmt;

***************
*** 180,208 ****

          /* Destroy the statement and free any results, cursors, etc. */
          SC_Destructor(stmt);
-
      }
      else if (fOption == SQL_UNBIND)
      {
          SC_unbind_cols(stmt);
-
      }
      else if (fOption == SQL_CLOSE)
      {
!         /* this should discard all the results, but leave the statement */
!         /* itself in place (it can be executed again) */
          if (!SC_recycle_statement(stmt))
          {
              /* errormsg passed in above */
              SC_log_error(func, "", stmt);
              return SQL_ERROR;
          }
-
      }
      else if (fOption == SQL_RESET_PARAMS)
      {
          SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
-
      }
      else
      {
--- 178,204 ----

          /* Destroy the statement and free any results, cursors, etc. */
          SC_Destructor(stmt);
      }
      else if (fOption == SQL_UNBIND)
      {
          SC_unbind_cols(stmt);
      }
      else if (fOption == SQL_CLOSE)
      {
!         /*
!          * this should discard all the results, but leave the statement
!          * itself in place (it can be executed again)
!          */
          if (!SC_recycle_statement(stmt))
          {
              /* errormsg passed in above */
              SC_log_error(func, "", stmt);
              return SQL_ERROR;
          }
      }
      else if (fOption == SQL_RESET_PARAMS)
      {
          SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
      }
      else
      {
***************
*** 216,223 ****
  }


!
! /**********************************************************************
   * StatementClass implementation
   */
  void
--- 212,218 ----
  }


! /*
   * StatementClass implementation
   */
  void
***************
*** 288,294 ****
          rv->nfld = 0;
          rv->parse_status = STMT_PARSE_NONE;

-
          /* Clear Statement Options -- defaults will be set in AllocStmt */
          memset(&rv->options, 0, sizeof(StatementOptions));
      }
--- 283,288 ----
***************
*** 298,304 ****
  char
  SC_Destructor(StatementClass *self)
  {
-
      mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc);
      if (STMT_EXECUTING == self->status)
      {
--- 292,297 ----
***************
*** 322,339 ****

      /*
       * the memory pointed to by the bindings is not deallocated by the
!      * driver
!      */
!
!     /*
!      * by by the application that uses that driver, so we don't have to
       * care
       */
      /* about that here. */
      if (self->bindings)
          free(self->bindings);

-
      /* Free the parsed table information */
      if (self->ti)
      {
--- 315,327 ----

      /*
       * the memory pointed to by the bindings is not deallocated by the
!      * driver but by the application that uses that driver, so we don't have to
       * care
       */
      /* about that here. */
      if (self->bindings)
          free(self->bindings);

      /* Free the parsed table information */
      if (self->ti)
      {
***************
*** 355,361 ****
          free(self->fi);
      }

-
      free(self);

      mylog("SC_Destructor: EXIT\n");
--- 343,348 ----
***************
*** 363,371 ****
      return TRUE;
  }

! /*    Free parameters and free the memory from the
!     data-at-execution parameters that was allocated in SQLPutData.
! */
  void
  SC_free_params(StatementClass *self, char option)
  {
--- 350,359 ----
      return TRUE;
  }

! /*
!  *    Free parameters and free the memory from the
!  *    data-at-execution parameters that was allocated in SQLPutData.
!  */
  void
  SC_free_params(StatementClass *self, char option)
  {
***************
*** 380,386 ****
      {
          if (self->parameters[i].data_at_exec == TRUE)
          {
-
              if (self->parameters[i].EXEC_used)
              {
                  free(self->parameters[i].EXEC_used);
--- 368,373 ----
***************
*** 427,435 ****
  }


! /*    Called from SQLPrepare if STMT_PREMATURE, or
!     from SQLExecute if STMT_FINISHED, or
!     from SQLFreeStmt(SQL_CLOSE)
   */
  char
  SC_recycle_statement(StatementClass *self)
--- 414,423 ----
  }


! /*
!  *    Called from SQLPrepare if STMT_PREMATURE, or
!  *    from SQLExecute if STMT_FINISHED, or
!  *    from SQLFreeStmt(SQL_CLOSE)
   */
  char
  SC_recycle_statement(StatementClass *self)
***************
*** 469,475 ****
              conn = SC_get_conn(self);
              if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
              {
-
                  QResultClass *res = CC_send_query(conn, "ABORT", NULL);

                  QR_Destructor(res);
--- 457,462 ----
***************
*** 518,528 ****
          QR_Destructor(self->result);
          self->result = NULL;
      }
-
-     /****************************************************************/
-     /* Reset only parameters that have anything to do with results */
-     /****************************************************************/

      self->status = STMT_READY;
      self->manual_result = FALSE;/* very important */

--- 505,514 ----
          QR_Destructor(self->result);
          self->result = NULL;
      }

+     /*
+      * Reset only parameters that have anything to do with results
+      */
      self->status = STMT_READY;
      self->manual_result = FALSE;/* very important */

***************
*** 538,546 ****

      self->lobj_fd = -1;

!     /* Free any data at exec params before the statement is executed */
!     /* again.  If not, then there will be a memory leak when */
!     /* the next SQLParamData/SQLPutData is called. */
      SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);

      return TRUE;
--- 524,534 ----

      self->lobj_fd = -1;

!     /*
!      * Free any data at exec params before the statement is executed
!      * again.  If not, then there will be a memory leak when
!      * the next SQLParamData/SQLPutData is called.
!      */
      SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);

      return TRUE;
***************
*** 550,556 ****
  void
  SC_pre_execute(StatementClass *self)
  {
-
      mylog("SC_pre_execute: status = %d\n", self->status);

      if (self->status == STMT_READY)
--- 538,543 ----
***************
*** 597,604 ****
  }


! /*    This function creates an error msg which is the concatenation */
! /*    of the result, statement, connection, and socket messages. */
  char *
  SC_create_errormsg(StatementClass *self)
  {
--- 584,593 ----
  }


! /*
!  *    This function creates an error msg which is the concatenation
!  *    of the result, statement, connection, and socket messages.
!  */
  char *
  SC_create_errormsg(StatementClass *self)
  {
***************
*** 640,646 ****
  {
      char        rv;

! /*    Create a very informative errormsg if it hasn't been done yet. */
      if (!self->errormsg_created)
      {
          self->errormsg = SC_create_errormsg(self);
--- 629,635 ----
  {
      char        rv;

!     /*    Create a very informative errormsg if it hasn't been done yet. */
      if (!self->errormsg_created)
      {
          self->errormsg = SC_create_errormsg(self);
***************
*** 660,669 ****
      return rv;
  }

! /*    Currently, the driver offers very simple bookmark support -- it is
!     just the current row number.  But it could be more sophisticated
!     someday, such as mapping a key to a 32 bit value
! */
  unsigned long
  SC_get_bookmark(StatementClass *self)
  {
--- 649,659 ----
      return rv;
  }

! /*
!  *    Currently, the driver offers very simple bookmark support -- it is
!  *    just the current row number.  But it could be more sophisticated
!  *    someday, such as mapping a key to a 32 bit value
!  */
  unsigned long
  SC_get_bookmark(StatementClass *self)
  {
***************
*** 683,689 ****
      char       *value;
      ColumnInfoClass *ci;

! /* TupleField *tupleField; */

      self->last_fetch_count = 0;
      ci = QR_get_fields(res);    /* the column info */
--- 673,679 ----
      char       *value;
      ColumnInfoClass *ci;

!     /* TupleField *tupleField; */

      self->last_fetch_count = 0;
      ci = QR_get_fields(res);    /* the column info */
***************
*** 692,702 ****

      if (self->manual_result || !globals.use_declarefetch)
      {
-
          if (self->currTuple >= QR_get_num_tuples(res) - 1 ||
              (self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1))
          {
-
              /*
               * if at the end of the tuples, return "no data found" and set
               * the cursor past the end of the result set
--- 682,690 ----
***************
*** 710,716 ****
      }
      else
      {
-
          /* read from the cache or the physical next tuple */
          retval = QR_next_tuple(res);
          if (retval < 0)
--- 698,703 ----
***************
*** 720,726 ****
          }
          else if (retval > 0)
              (self->currTuple)++;/* all is well */
-
          else
          {
              mylog("SQLFetch: error\n");
--- 707,712 ----
***************
*** 753,759 ****

      for (lf = 0; lf < num_cols; lf++)
      {
-
          mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self,
self->bindings,self->bindings[lf].buffer); 

          /* reset for SQLGetData */
--- 739,744 ----
***************
*** 809,821 ****
                      result = SQL_SUCCESS_WITH_INFO;
                      break;

!                 case COPY_GENERAL_ERROR:        /* error msg already
!                                                  * filled in */
                      SC_log_error(func, "", self);
                      result = SQL_ERROR;
                      break;

!                     /* This would not be meaningful in SQLFetch. */
                  case COPY_NO_DATA_FOUND:
                      break;

--- 794,806 ----
                      result = SQL_SUCCESS_WITH_INFO;
                      break;

!                 /* error msg already filled in */
!                 case COPY_GENERAL_ERROR:
                      SC_log_error(func, "", self);
                      result = SQL_ERROR;
                      break;

!                 /* This would not be meaningful in SQLFetch. */
                  case COPY_NO_DATA_FOUND:
                      break;

***************
*** 889,901 ****
              CC_set_in_trans(conn);
      }

-
-
      oldstatus = conn->status;
      conn->status = CONN_EXECUTING;
      self->status = STMT_EXECUTING;

-
      /* If it's a SELECT statement, use a cursor. */

      /*
--- 874,883 ----
***************
*** 905,923 ****
      /* in copy_statement... */
      if (self->statement_type == STMT_TYPE_SELECT)
      {
-
          char        fetch[128];

          mylog("       Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);

-
          /* send the declare/select */
          self->result = CC_send_query(conn, self->stmt_with_params, NULL);

          if (globals.use_declarefetch && self->result != NULL &&
              QR_command_successful(self->result))
          {
-
              QR_Destructor(self->result);

              /*
--- 887,902 ----
***************
*** 935,954 ****
               * will correct for any discrepancies in sizes and adjust the
               * cache accordingly.
               */
-
              sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);

              self->result = CC_send_query(conn, fetch, &qi);
          }
-
          mylog("     done sending the query:\n");
-
-
-
      }
      else
!     {                            /* not a SELECT statement so don't use a
!                                  * cursor */
          mylog("      it's NOT a select statement: stmt=%u\n", self);
          self->result = CC_send_query(conn, self->stmt_with_params, NULL);

--- 914,928 ----
               * will correct for any discrepancies in sizes and adjust the
               * cache accordingly.
               */
              sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);

              self->result = CC_send_query(conn, fetch, &qi);
          }
          mylog("     done sending the query:\n");
      }
      else
!     {
!         /* not a SELECT statement so don't use a cursor */
          mylog("      it's NOT a select statement: stmt=%u\n", self);
          self->result = CC_send_query(conn, self->stmt_with_params, NULL);

***************
*** 967,973 ****
              QR_Destructor(res);
              CC_set_no_trans(conn);
          }
-
      }

      conn->status = oldstatus;
--- 941,946 ----
***************
*** 976,982 ****
      /* Check the status of the result */
      if (self->result)
      {
-
          was_ok = QR_command_successful(self->result);
          was_nonfatal = QR_command_nonfatal(self->result);

--- 949,954 ----
***************
*** 985,992 ****
          else
              self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND;

!         self->currTuple = -1;    /* set cursor before the first tuple in
!                                  * the list */
          self->current_col = -1;
          self->rowset_start = -1;

--- 957,964 ----
          else
              self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND;

!         /* set cursor before the first tuple in the list */
!         self->currTuple = -1;
          self->current_col = -1;
          self->rowset_start = -1;

***************
*** 1010,1018 ****
              CC_abort(conn);
      }
      else
!     {                            /* Bad Error -- The error message will be
!                                  * in the Connection */
!
          if (self->statement_type == STMT_TYPE_CREATE)
          {
              self->errornumber = STMT_CREATE_TABLE_ERROR;
--- 982,989 ----
              CC_abort(conn);
      }
      else
!     {
!         /* Bad Error -- The error message will be in the Connection */
          if (self->statement_type == STMT_TYPE_CREATE)
          {
              self->errornumber = STMT_CREATE_TABLE_ERROR;
Index: src/interfaces/odbc/tuple.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/tuple.c,v
retrieving revision 1.12
diff -c -r1.12 tuple.c
*** src/interfaces/odbc/tuple.c    2001/03/27 04:00:55    1.12
--- src/interfaces/odbc/tuple.c    2001/03/28 16:53:22
***************
*** 1,17 ****
! /* Module:            tuple.c
   *
!  * Description:        This module contains functions for setting the data for individual
!  *                    fields (TupleField structure) of a manual result set.
   *
-  * Important Note:    These functions are ONLY used in building manual result sets for
-  *                    info functions (SQLTables, SQLColumns, etc.)
-  *
   * Classes:            n/a
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #include "tuple.h"
--- 1,20 ----
! /*-------
!  * Module:            tuple.c
   *
!  * Description:        This module contains functions for setting the data
!  *                    for individual fields (TupleField structure) of a
!  *                    manual result set.
!  *
!  * Important Note:    These functions are ONLY used in building manual
!  *                    result sets for info functions (SQLTables,
!  *                    SQLColumns, etc.)
   *
   * Classes:            n/a
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *-------
   */

  #include "tuple.h"
***************
*** 38,44 ****
  set_tuplefield_int2(TupleField *tuple_field, Int2 value)
  {
      char        buffer[10];
-

      sprintf(buffer, "%d", value);

--- 41,46 ----
Index: src/interfaces/odbc/tuplelist.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/odbc/tuplelist.c,v
retrieving revision 1.11
diff -c -r1.11 tuplelist.c
*** src/interfaces/odbc/tuplelist.c    2001/03/27 04:00:55    1.11
--- src/interfaces/odbc/tuplelist.c    2001/03/28 16:53:22
***************
*** 1,14 ****
! /* Module:            tuplelist.c
   *
!  * Description:        This module contains functions for creating a manual result set
!  *                    (the TupleList) and retrieving data from it for a specific row/column.
   *
   * Classes:            TupleListClass (Functions prefix: "TL_")
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *
   */

  #include <stdlib.h>
--- 1,16 ----
! /*--------
!  * Module:            tuplelist.c
   *
!  * Description:        This module contains functions for creating a manual
!  *                    result set (the TupleList) and retrieving data from
!  *                    it for a specific row/column.
   *
   * Classes:            TupleListClass (Functions prefix: "TL_")
   *
   * API functions:    none
   *
   * Comments:        See "notice.txt" for copyright and license information.
!  *--------
   */

  #include <stdlib.h>
***************
*** 25,31 ****
      rv = (TupleListClass *) malloc(sizeof(TupleListClass));
      if (rv)
      {
-
          rv->num_fields = fieldcnt;
          rv->num_tuples = 0;
          rv->list_start = NULL;
--- 27,32 ----
***************
*** 134,140 ****
      }
      else if (start_is_closer)
      {
-
          /*
           * the shortest way is to start the search from the head of the
           * list
--- 135,140 ----
***************
*** 177,187 ****
  }


-
  char
  TL_add_tuple(TupleListClass *self, TupleNode *new_field)
  {
-
      /*
       * we append the tuple at the end of the doubly linked list of the
       * tuples we have already read in
--- 177,185 ----
***************
*** 200,206 ****
      }
      else
      {
-
          /*
           * there is already an element in the list, so add the new one at
           * the end of the list
--- 198,203 ----

pgsql-patches by date:

Previous
From: Maurizio Ortolan
Date:
Subject: Error in the date field (with NULL value...).Thanks!
Next
From: Hiroshi Inoue
Date:
Subject: Re: Re: [ODBC] Cleanup of ODBC