http://www.perlmonks.org?node_id=1083304


in reply to Strawberry Perl 64bit on Win7 crashes on DBI-function

That is a lot of data sources. Perhaps someone ca see a flaw in the XS code that DBD::ODBC uses:

void data_sources(drh, attr = NULL) SV* drh; SV* attr; PROTOTYPE: $;$ PPCODE: { #ifdef DBD_ODBC_NO_DATASOURCES /* D_imp_drh(drh); imp_drh->henv = SQL_NULL_HENV; dbd_error(drh, (RETCODE) SQL_ERROR, "data_sources: SOLID d +oesn't implement SQLDataSources()");*/ XSRETURN(0); #else int numDataSources = 0; UWORD fDirection = SQL_FETCH_FIRST; RETCODE rc; UCHAR dsn[SQL_MAX_DSN_LENGTH+1+9 /* strlen("DBI:ODBC:") */]; SWORD dsn_length; UCHAR description[256]; SWORD description_length; D_imp_drh(drh); if (!imp_drh->connects) { rc = SQLAllocEnv(&imp_drh->henv); if (!SQL_ok(rc)) { imp_drh->henv = SQL_NULL_HENV; dbd_error(drh, rc, "data_sources/SQLAllocEnv"); XSRETURN(0); } } strcpy(dsn, "dbi:ODBC:"); while (1) { rc = SQLDataSources(imp_drh->henv, fDirection, dsn+9, /* strlen("DBI:ODBC:") */ SQL_MAX_DSN_LENGTH, &dsn_length, description, sizeof(description), &description_length); if (!SQL_ok(rc)) { if (rc != SQL_NO_DATA_FOUND) { /* * Temporarily increment imp_drh->connects, so * that dbd_error uses our henv. */ imp_drh->connects++; dbd_error(drh, rc, "data_sources/SQLDataSources"); imp_drh->connects--; } break; } ST(numDataSources++) = newSVpv(dsn, dsn_length+9 /* strlen("db +i:ODBC:") */ ); fDirection = SQL_FETCH_NEXT; } if (!imp_drh->connects) { SQLFreeEnv(imp_drh->henv); imp_drh->henv = SQL_NULL_HENV; } XSRETURN(numDataSources); #endif /* no data sources */ }

Replies are listed 'Best First'.
Re^2: Strawberry Perl 64bit on Win7 crashes on DBI-function
by Corion (Patriarch) on Apr 23, 2014 at 09:31 UTC

    One thing that strikes me as odd is that MSDN on SQLDataSources documents the BufferLength2 parameter as

    [Input] Length in characters of the *Description buffer.

    The value passed to it is sizeof(description). This is all well, as long as sizeof(UCHAR) == sizeof(char), but I don't know if that is actually true, as I don't do much C. UCHAR could be unsigned char, but it could also be Unicode char. Personally, I would try to avoid the direct sizeof() and declare a constant (say) DESCRIPTION_SIZE= 256, and then use

    const DESCRIPTION_SIZE= 256; UCHAR description[ DESCRIPTION_SIZE ]; ... SQLDataSources( ... description, DESCRIPTION_SIZE, ... );

    ... but I doubt that this is the problematic part, as it would imply an "overly long" description of over 256 bytes in one of the ODBC data sources.

      Actually something along these lines would make sense to me, because i suspect some sort of problem with the fact that my windows being a 64bit system.

      One of the differences between 64bit and 32bit is of course the different return values for the sizeof() function in c.

      I think if one is not careful there, some code segment could easily work like a charm on windows 32bit but cause serious problems on windows 64bit.

      I installed the DBI- and DBD:ODBC-packages using something like cpan install DBI calling the cpan.bat from the 64bit-installation of strawberry perl (again 5.18.1).

      So i thought the packages beeing installed should definetly be working on windows 64bit. But maybe this is just not necessarily the case?

      It is a fresh perl-installation and the only thing i added were the two mentioned packages and the Modern:Perl-package to test the code suggested above.

        I didn't write the data_sources method but I look after DBD::ODBC these days. I don't see a 64bit issue and inspecting the code I cannot see any issue although there are things I might have done differently.

        I still suspect it is something to do with the large number of DSNs you have. If you download DBD::ODBC and build it yourself I can suggest a few small changes that might help identify the issue.

        Download the latest DBD::ODBC, and untar it into a dir. Open a strawberry perl shell session and change to the dir above. Edit the file ODBC.xs and delete the function data_sources and replace it with the one below:

        void data_sources(drh, attr = NULL) SV* drh; SV* attr; PROTOTYPE: $;$ PPCODE: { #ifdef DBD_ODBC_NO_DATASOURCES /* D_imp_drh(drh); imp_drh->henv = SQL_NULL_HENV; dbd_error(drh, (RETCODE) SQL_ERROR, "data_sources: SOLID d +oesn't implement SQLDataSources()");*/ XSRETURN(0); #else int numDataSources = 0; SQLUSMALLINT fDirection = SQL_FETCH_FIRST; RETCODE rc; SQLCHAR dsn[SQL_MAX_DSN_LENGTH+1+9 /* strlen("DBI:ODBC:") */]; SQLSMALLINT dsn_length; SQLCHAR description[256]; SQLSMALLINT description_length; D_imp_drh(drh); if (!imp_drh->connects) { rc = SQLAllocEnv(&imp_drh->henv); if (!SQL_ok(rc)) { imp_drh->henv = SQL_NULL_HENV; dbd_error(drh, rc, "data_sources/SQLAllocEnv"); XSRETURN(0); } } strcpy(dsn, "dbi:ODBC:"); while (1) { description[0] = '\0'; rc = SQLDataSources(imp_drh->henv, fDirection, dsn+9, /* strlen("dbi:ODBC:") */ SQL_MAX_DSN_LENGTH, &dsn_length, description, sizeof(description), &description_length); if (!SQL_ok(rc)) { if (rc != SQL_NO_DATA_FOUND) { /* * Temporarily increment imp_drh->connects, so * that dbd_error uses our henv. */ imp_drh->connects++; dbd_error(drh, rc, "data_sources/SQLDataSources"); imp_drh->connects--; } break; } printf("/%s/ (%d), /%s/ (%d)\n", (dsn + 9), dsn_length, description, description_length); ST(numDataSources++) = newSVpv(dsn, dsn_length+9 /* strlen("db +i:ODBC:") */ ); fDirection = SQL_FETCH_NEXT; } if (!imp_drh->connects) { SQLFreeEnv(imp_drh->henv); imp_drh->henv = SQL_NULL_HENV; } XSRETURN(numDataSources); /* return indicating # + items on stack */ #endif /* no data sources */ }

        Now type perl Makefile.PL, then dmake and it should build you a DBD::ODBC. Now run something like the following:

        perl -Ic:\path_to_dbd_odbc_dir\blib\lib -Ic:\path_to_dbd_odbc_dir\blib +\arch -le "use DBI; my @a = DBI->data_sources('ODBC');"

        Replace c:\path_to_dbd_odbc_dir as per your machine and where you unpacked DBD::ODBC. It should output a list of your dsns and lengths - what was the output and did it crash? If it does not crash, take the printf line out (all from printf to the semi colon), rebuild and try again? Does it work now?

Re^2: Strawberry Perl 64bit on Win7 crashes on DBI-function
by theman824 (Novice) on Apr 23, 2014 at 12:55 UTC
    Actually anything i do in my script using the DBD::ODBC-package works. Including connecting, sending an sql and fetching the result from the DB2-database.

    The crash occurs calling the above mentioned function from the DBI-package. It should merly list all the configured ODBC-DSNs on the given windows machine.

Re^2: Strawberry Perl 64bit on Win7 crashes on DBI-function
by Anonymous Monk on Apr 23, 2014 at 09:29 UTC

    That is a lot of data sources. Perhaps someone ca see a flaw in the XS code that DBD::ODBC uses:

    LOL!