Menu

#12 Long queries son't seem to work

open
nobody
None
5
2002-12-27
2002-12-27
Anonymous
No

Hi,

ODBCSS is more or less what I want seeing I'm stuck
with an Access database and (luckily) an APache
webserver on o Unix box. It works for me except when
my queries get longer and somewhat complexer. When I
request a couple of rows from let's say three tables with
a large WHERE clause it dies on me instantly. I don't
even think it reaches the ODBC socket.

I don't know if the problem lies with the lenght of the
queries or the complexity. When I run the exact same
query in Access there are no problems. I took extra care
with the query syntax ( no "!" and no quotes ).

If this is a (know) bug is there a fix for it. I could modify
the code, but I would like to concentrate on developing
my own app.

Thanks in advance,

Michel

Discussion

  • Michel Koning

    Michel Koning - 2003-01-03

    Logged In: YES
    user_id=676117

    I did some more investigation into my problem and the issue
    seems to be that a WHERE something LIKE '*abc*'
    statement doesn't seem to work. This could be due to the
    wildcards. However I believe MS-Access wants "*". So how
    do I get a wildcard through to Access seems to be the
    question now.

    Regards,

    Michel

     
  • Michel Koning

    Michel Koning - 2003-01-06

    Logged In: YES
    user_id=676117

    As a comment on my last post, using LIKE '%abc%' does
    work for ODBCSS. This way my wildcard do get send to the
    Access database.

    Mies

     
  • Nobody/Anonymous

    Logged In: NO

    you can increase the size of the buffer in main-server.h

    const int kBufferSize = 1024;

    personally i am using 3096

    don't forget to modify also the buffer size of the odbcclient

    i am also using odbc socket server with msaccess

     
  • Michael Collinson

    Logged In: YES
    user_id=980704

    I've had similar problem, simple but large queries taking 25
    minutes to return or just hanging, and was able to perform
    great performance boost on large query results as follows:

    1) If using PHP, replace the ODBC Socket Server class PHP
    client class fgets() loop with the following:

    do {
    //Try some large number:
    //$data = fread($fToOpen, 8192);
    //$data = fread($fToOpen, 16384);
    $data = fread($fToOpen, 32768);
    if (strlen($data) == 0) {
    break;
    }
    $sReturn .= $data;
    } while (true);

    2) As per bug reports, increase the buffer size in main-server.h

    const int kBufferSize = 1024;

    Also apply the memory leak fix reported in 617441.

    3) The real problem lies in the Microsoft function

    //now, execute the SQL Statement
    Cmd1->CommandText = T2OLE((char*)sSQL.c_str());

    in ExecSQL() and the way RecordSetToMSDTD() is forced to
    do a temporary write of the query result to disk in order to get
    it into XML.

    I found the best solution was to port to Microsoft .NET 1.1
    which is more XML friendly and the SQL execution code for
    large queries on MS Access databases several orders of
    magnitude faster. Here is my code. Note though:

    - There is no MS Access ODBC driver (currently) for .NET. The
    solution below forces you to change from using a DSN to
    identify the database you want to use to an absolute directory
    path like this:

    sConnectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data
    Source=c:\\mydir\\mydatabases\\abigdatabase.mdb";

    - Caveat Emptor. I am now an occasional programmer and
    certainly NOT a MS Windows programmer. The code works for
    me but it is probably beginner quality.

    - If you try to recompile in VC++ .NET 2003, you'll get several
    errors you'll need to fix elsewhere in the code.

    main-server.cpp

    Change the header includes so:

    ------------------------------------------------------------
    #include "stdio.h"
    #include "io.h"

    #include "stdafx.h"
    #include "main-server.h"
    #include <fstream>
    //.NET #include "iostream.h"

    #include <iostream>
    using namespace std;

    /* Added for .NET OLE port: */
    #using <mscorlib.dll>
    #using <System.dll>
    #using <System.XML.dll>
    #using <System.Data.dll>

    using namespace System;
    using namespace System::Data;
    using namespace System::Xml;
    using namespace System::Data::OleDb;
    //using namespace System::Data::SqlClient;
    /* End of .NET OLE addition */
    ------------------------------------------------------------

    Replace the ExecSQL function so:

    ------------------------------------------------------------
    -------------
    std::string ExecSQL(std::string sConnectionString, std::string
    sSQL)
    {
    // Convert to .NET managed strings
    System::String* strConnectionString =
    sConnectionString.c_str();
    System::String* strSQL = sSQL.c_str();

    //Example: OleDbConnection * mySqlConnection = new
    OleDbConnection(S"Provider=Microsoft.Jet.OLEDB.4.0;Data

    Source=c:\\mydir\\mydbs\\agreatbigdb.mdb");
    OleDbConnection * mySqlConnection = new
    OleDbConnection(strConnectionString);

    try
    {
    LogEvent("ExecSQL 1 Connect ...", 1);
    mySqlConnection->Open();

    //create the datareader object to connect to table
    LogEvent("ExecSQL 2 Exec SQL...", 1);
    OleDbDataAdapter * adapter = new
    OleDbDataAdapter();
    adapter->SelectCommand = new
    OleDbCommand(strSQL, mySqlConnection);
    //adapter->SelectCommand = new
    OleDbCommand("SELECT * FROM postcodepredictions WHERE
    code = '2000' ORDER BY isunit, code,

    periodend ASC", mySqlConnection);
    DataSet * dataset;
    dataset = new DataSet("wholetable");
    adapter->Fill(dataset);

    /* GetXml returns the XML representation of the
    DataSet without schema information. To write the schema
    information

    from the DataSet (as XML Schema) to a string, use
    GetXmlSchema.
    *
    * To write a DataSet to a file, stream, or XmlWriter,
    use the WriteXml method. The first parameter you pass to

    WriteXml is the destination of the XML output. For example,
    pass a string containing a file name, a System.IO.TextWriter
    object, and so

    on. You can pass an optional second parameter of an
    XmlWriteMode to specify how the XML output is to be written.
    */
    LogEvent("ExecSQL 3 Get XML ...", 1);
    String * xmlDS = dataset->GetXml();
    //String * xmlDS = dataset->GetXmlSchema();
    //DEBUG Console::WriteLine(xmlDS);

    //close the connection
    LogEvent("ExecSQL 4 Close connection ...", 1);
    mySqlConnection->Close();

    /* Programming note:
    Convert std::string to System::string:
    std::string strOld = "Test";
    System::String* strNew = strOld.c_str();
    */

    /* Convert managed string to C/C++ string */
    LogEvent("ExecSQL 5 String conversion ...", 1);
    using namespace System::Runtime::InteropServices;
    const char* str = (const char*)
    (Marshal::StringToHGlobalAnsi(xmlDS)).ToPointer();
    LogEvent("ExecSQL 6 Returning XML ...", 2);
    // use str as you wish or copy it elsewhere
    // free string
    // Marshal::FreeHGlobal(IntPtr((void*)str));
    //or call function
    // MarshalString ( xmlDS, std::string& os );
    return str; //must be std::string
    }

    //Some usual exception handling
    catch(Exception * e)
    {
    Console::WriteLine(e->ToString());
    using namespace System::Runtime::InteropServices;
    const char* str = (const char*)
    (Marshal::StringToHGlobalAnsi(e->ToString())).
    ToPointer();
    LogEvent(str, 3);
    }
    __finally
    {
    mySqlConnection->Close();
    }

    }
    ------------------------------------------------------------
    -------------

    Mike Collinson

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.