Thread: Cleanup of ODBC

Cleanup of ODBC

From
Bruce Momjian
Date:
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.

--
  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

Re: [ODBC] Cleanup of ODBC

From
Tom Lane
Date:
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

Re: [ODBC] Cleanup of ODBC

From
Bruce Momjian
Date:
> 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.

OK, but will people complain if I make comment changes in 7.2 and mess
up their patches and the 7.1 patches people submit?

--
  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

Re: [ODBC] Cleanup of ODBC

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
>> In short: save it for 7.2.

> OK, but will people complain if I make comment changes in 7.2 and mess
> up their patches and the 7.1 patches people submit?

Not half as loud as they'll complain if we ship a broken ODBC in 7.1.

At this stage of the game we should only be applying bug fixes, and
only fairly critical ones at that ...

            regards, tom lane

Re: Re: [ODBC] Cleanup of ODBC

From
The Hermit Hacker
Date:
On Wed, 28 Mar 2001, Bruce Momjian wrote:

> > 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.
>
> OK, but will people complain if I make comment changes in 7.2 and mess
> up their patches and the 7.1 patches people submit?

Who cares?  Man, I'd hate for this project to ever get to the size of
Linux or FreeBSD ... we'd be spending so much time "cleaning" what doesn't
need to be cleaned that we'd get no work done *sigh*



Re: Re: [ODBC] Cleanup of ODBC

From
Bruce Momjian
Date:
> > OK, but will people complain if I make comment changes in 7.2 and mess
> > up their patches and the 7.1 patches people submit?
>
> Who cares?  Man, I'd hate for this project to ever get to the size of
> Linux or FreeBSD ... we'd be spending so much time "cleaning" what doesn't
> need to be cleaned that we'd get no work done *sigh*

I am cleaning because I really can't do much else right now, and people
complain other times because they have open patches.  Anyway, no ODBC
people have complained yet.  I tried this earlier in beta and messed up
Hiroshi because he was working in this area.

--
  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

Re: Re: [ODBC] Cleanup of ODBC

From
Bruce Momjian
Date:
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 ----

Re: Re: [ODBC] Cleanup of ODBC

From
Hiroshi Inoue
Date:
Bruce Momjian wrote:
>
> 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.
>

Hmm what a big patch !
I'm also holding a patch as I posted in pgsql-odbc.
Well when would you apply your patch ?

regards,
Hiroshi Inoue

Re: Re: [ODBC] Cleanup of ODBC

From
Bruce Momjian
Date:
> Bruce Momjian wrote:
> >
> > 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.
> >
>
> Hmm what a big patch !
> I'm also holding a patch as I posted in pgsql-odbc.
> Well when would you apply your patch ?

Once we branch the tree for 7.2.

I just looked at your patch dated March 26 with subject "[ODBC] ODBC
changes about parameter handling."  I don't see much duplicate change in
the two patches.  If you want to apply yours first after 7.2 branches, I
will then apply mine and fix any rejects.

--
  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