[freetds] Procedure or function has too many arguments specified

Man Min Yan manmin_yan at yahoo.com.au
Tue Nov 4 00:56:03 EST 2008


Hi,

I think I have found the cause to this problem. The following patch fixes the problem, but I don't know the code well enough to know whether this is the proper fix or not.

*** mem.c.orig  2008-11-04 16:35:39.000000000 +1100
--- mem.c       2008-11-04 16:23:24.000000000 +1100
***************
*** 99,104 ****
--- 99,105 ----
        for (curr = tds->dyns; curr != NULL; curr = curr->next)
                if (!strcmp(curr->id, id)) {
                        /* id already exists! just return it */
+                       curr->num_id = 0;
                        return curr;
                }

This is what's causing the problem to occur:

- The algorithm in the tds_get_dynid function in tds/query.c will always return the same 65535 ids in a single session (The code increments the variable inc_num everytime the function is called, but then restricts its value with incr & 0xffff). This means that after the 65536's iteration of a query through the sp_prepare/sp_execute cycle, the id is the same as iteration 1.

- In tds_submit_prepare, the id from tds_get_dynid is passed to tds_alloc_dynamic. When given a previously used id, tds_alloc_dynamic will return the previously allocated structure. However, it doesn't clear its contents (in particular, the num_id variable). This causes the num_id returned from the server to be ignored in tds_process_tokens, in the TDS_PARAM_TOKEN case, where it does
        if (tds->internal_sp_called == TDS_SP_PREPARE 
                        && tds->cur_dyn && ***tds->cur_dyn->num_id == 0*** && curcol->column_cur_size > 0) {
                        tds->cur_dyn->num_id = *(TDS_INT *) curcol->column_data;
                    }


This later causes freetds to try to sp_execute the wrong prepared statement.


Man Min



----- Original Message ----
From: Man Min Yan <manmin_yan at yahoo.com.au>
To: freetds at lists.ibiblio.org
Sent: Friday, 17 October, 2008 1:25:27 PM
Subject: [freetds] Procedure or function has too many arguments specified

Hi,
I am getting the above error when trying to execute over 65535 statements (tested with insert, update and select) using DBD::ODBC, unixODBC and freeTDS (both 0.82 stable and 0.83 20081016) talking to SQL Server 2000 and 2005. I can consistently replicate the problem with the script below.

Please note:
- my freetds.conf is configured with 'tds version = 8.0'
- I'm running on f7, with unixODBC 2.2.12-5, DBD::ODBC 1.13
- the script runs fine if I use DBD::ODBC, unixODBC, mysql-connector (sorts of eliminates DBD::ODBC, unixODBC as the culprits)
- the script runs fine if I use DBD::Proxy (eliminates the dbms side as the culprit)
- the script only fails if there is a prepared select present (even if never used).
- it always fails on record 65536 (16-bit number somewhere??)
- I've attached an extract of the freetds dump log for the last couple of records.

Any help in solving this problem would be greatly appreciated. Thanks.
---
#!/usr/local/bin/perl -w

use strict;
use DBI;

# The table 'test_table' has the following structure
#    create table test_table (id int not null, value varchar(10))

my $dsn = 'dbi:ODBC:sqlserver'; my $user='xx'; my $pass='xx';
#my $dsn = 'dbi:ODBC:mysql'; my $user='xx'; my $pass='xx';
#my $dsn = 'dbi:Proxy:hostname=myserver;port=40000;dsn=dbi:ODBC:sqlserver'; my $user='xx'; my $pass='xx';
my $dbh = DBI->connect($dsn, $user, $pass,
    {
        PrintError => 0,
        RaiseError => 0,
        AutoCommit => 1,
    }) or die $DBI::errstr;
$dbh->do('truncate table test_table') or die $dbh->errstr;

#my $updSth = $dbh->prepare('update test_table set value=? where id=?') or die $dbh->errstr;
my $selSth = $dbh->prepare('select * from test_table where id=?') or die $dbh->errstr;
my $insSth = $dbh->prepare('insert into test_table values (?, ?)') or die $dbh->errstr;

$| = 1;
my $maxIteration = 100000;
for (my $i = 1; $i <= $maxIteration; $i++)
{
    print "$i\r";
    $insSth->execute($i, $i) or die "Fail execute with $i - ", $insSth->errstr;
    #$updSth->execute('v' . $i, $i) or die "Fail execute with $i - ", $updSth->errstr;
    #$selSth->execute($i) or die "Fail execute with $i - ", $selSth->errstr;
    #$selSth->finish();
}


      Search 1000's of available singles in your area at the new Yahoo!7 Dating. Get Started http://au.dating.yahoo.com/?cid=53151&pid=1011


More information about the FreeTDS mailing list