[freetds] SQLMoreResults and odbc/unittests/rpc.c

ZIGLIO, Frediano, VF-IT Frediano.Ziglio at vodafone.com
Wed Jul 12 10:26:56 EDT 2006


> 
> > From: Frediano Ziglio
> > Sent: Wednesday, July 12, 2006 1:08 AM
> > 
> > Well, currently test should work, I tested it with ms odbc and it
> > returns 3 resultset (and IMO it has to do so...). So the only
> > problem is that SQLMoreResults returns one more SQL_SUCCESS...
> > 
> > Il giorno mar, 11/07/2006 alle 18.44 -0400, Lowden, James K ha
> > scritto:
> > 
> > > The problem is row_count=1; it should be TDS_NO_COUNT.
> > ...
> > > I hope that by fixing this, we'll make DBD::ODBC happy.
> > > 
> > 
> > ?? according to http://freetds.sourceforge.net/out/test/test.1.html
> > DBD::ODBC is already happy..
> 
> Sometimes DBD::ODBC is happy.  But look at this output:
> 
> === begin ===
> $ perl ~/tmp/odbc_rpc.pl [...]  simdb..IsFreeTdsBroken
>   Perl            : 5.008       (alpha-dec_osf)
>   OS              : dec_osf     (4.0g)
>   DBI             : 1.50
>   DBD::Sponge     : 11.10
>   DBD::Proxy      : 0.2004
>   DBD::ODBC       : 1.13
>   DBD::Multiplex  : 0.9
>   DBD::File       : 0.33
>   DBD::ExampleP   : 11.12
>   DBD::DBM        : 0.03
> odbc_async_exec is: 0
>                          SQL_DM_VER     03.52.0002.0002
>                     SQL_DRIVER_NAME     libtdsodbc.so
>                      SQL_DRIVER_VER     0.64RC3
>                       SQL_DBMS_NAME     Microsoft SQL Server
>                        SQL_DBMS_VER     08.00.2162
>                        SQL_ODBC_VER     03.52
>                 SQL_DRIVER_ODBC_VER     03.00
>                SQL_DATA_SOURCE_NAME     mpquant
>                     SQL_SERVER_NAME     AC2KAMA0848
>                   SQL_DATABASE_NAME     master
> Binding parameter #1, the return code
> 
> Executing: "{? = call simdb..IsFreeTdsBroken }" with parameters ''
> execute returned: '-1'
> Result #1:
> [LatestInputsmDate]
> '2006-07-01 00:00:00'
> Result #2:
> ===> state: HY010 msg: Function sequence error
> DBD::ODBC::st fetchrow failed: (DBD: st_fetch/SQLFetch err=-1) at
> /usr/users2/jklowden/tmp/odbc_rpc.pl line 133.
> (return status is 0)
> === end ===
> 
> To remind you, the procedure selects a smalldatetime row (1 
> column) and
> returns 0:
> 
> CREATE procedure IsFreeTdsBroken
> as begin
> 
>         select LatestInputsmDate = max(smDate)
>         from smdates
> 
>         return 0
> end
> 
> The loop continues to the second "phantom" resultset because 
> 
> 	while ( $sth->{Active} ) 
> 
> evaluates to TRUE twice.  That might be because SQLMoreResults
> "succeeds" one extra time. 
> 

Ok, I just discovered the problem... 

Here is the patch 

diff -u -1 -0 -r1.415 odbc.c
--- src/odbc/odbc.c     11 Jul 2006 22:00:46 -0000      1.415
+++ src/odbc/odbc.c     12 Jul 2006 14:11:25 -0000
@@ -2926,21 +2942,21 @@
                        break;

                /*
                 * TODO test flags ? check error and change result ?
                 * see also other DONEINPROC handle (below)
                 */
                case TDS_DONEINPROC_RESULT:
                        if (stmt->dbc->env->attr.odbc_version ==
SQL_OV_ODBC3)
                                flag |= TDS_STOPAT_MSG;
                        if (done_flags & TDS_DONE_COUNT) {
-                               if (stmt->row_count == TDS_NO_COUNT)
+                               if (1 || stmt->row_count ==
TDS_NO_COUNT)
                                        stmt->row_count =
tds->rows_affected;
                                else
                                        stmt->next_row_count =
tds->rows_affected;
                        }
                        if (done_flags & TDS_DONE_ERROR)
                                stmt->errs.lastrc = SQL_ERROR;
                        /* TODO perhaps it can be a problem if SET
NOCOUNT ON, test it */
 #if 0
                        tds_free_all_results(tds);
                        odbc_populate_ird(stmt);
diff -u -1 -0 -r1.13 moreandcount.c
--- src/odbc/unittests/moreandcount.c   14 Apr 2005 11:35:46 -0000
1.13
+++ src/odbc/unittests/moreandcount.c   12 Jul 2006 14:11:25 -0000
@@ -91,21 +91,21 @@
        printf("Result %d\n", ++n);
        CHECK_COLS(1);
        CHECK_ROWS(-1);
        Fetch(SQL_SUCCESS);
        CHECK_COLS(1);
        CHECK_ROWS(-1);
        Fetch(SQL_NO_DATA);
        CHECK_COLS(1);
        if (prepare) {
                /* MS driver collapse 2 recordset... very bad */
-               if (!driver_is_freetds()) {
+               if (1 || !driver_is_freetds()) {
                        CHECK_ROWS(2);
                } else {
                        CHECK_ROWS(1);
                        NextResults(SQL_SUCCESS, __LINE__);
                        CHECK_ROWS(2);
                        CHECK_COLS(0);
                }
        } else {
                CHECK_ROWS(1);
                NextResults(SQL_SUCCESS, __LINE__);

well... it currently make if always true...

So the quesion is why are there lines presents?? The key is the comment
above in moreandcount.c:

   /* MS driver collapse 2 recordset... very bad */

consider something like

   select * from table
   delete from table 

using prepared statements or inside a rpc it produce

   ROWFMT
   ROW
   ROW
   ...
   DONEINPROC with row number (assume X)
   DONEINPROC with row number (assume Y)

MS odbc returns a single recordset of X row and returns Y row numbers
(strange but true). For this reasons we collected second row count in
different location in order to be able to produce the "phanton
recordset"... now something (DM or DBD::ODBC) don't like this strange
recordset without rows, columns and messages... what should we do??
Mimic MS behavior (that is very easy) ?? Discard the phantom??

freddy77




More information about the FreeTDS mailing list