I am having a weird problem using the TADOQuery
component.
I currently work at a place where they are using Borland C++Builder applications that run on a Windows XP VM. So we want to move to Windows 7 and serve it as a terminal so employees can receive new machines with Windows 10 without the need to create Win XP VM on each machine again.
Currently the application uses BDE components and it works great on XP. We created a Win7 64bit VM for testing, and installed the necessary driver etc, but BDE just won't work. When I try to login through the SQL Explorer that comes with Borland, it just hangs. It sends the request but never gets a response. I spent more than a week trying to debug this issue, but didn't get anywhere with it.
Anyways, I gave up on BDE and wanted to try to change to ADO. So I started by simply creating a TDBGrid
and fill it with data using ADO components. It worked great on both XP and Win7! So now I am trying to convert the applications' BDE components (TDataBase
, TQuery
, etc) to ADO components.
I came across an interesting issue when trying to use parameters. Here is a query example:
SELECT t1.SEC_CODE, t1.CODE, t1.CTRL_NUM, t1.CHECK_CODE,
t1.CHECK_NO, t1.CLIENT_ID, t1.AMOUNT, t1.TRANS_NO, decode(t2.prefix,null,t2.name,t2.name||', '||t2.prefix) as fullName,
t1.ENTRY_DATE, t1.DEPOSIT_DATE, t1.ACCT_COMMENT, t2.NAME, t2.PREFIX
FROM ACCOUNTING.ACCT_CHECK_IN t1, OISC.CLIENT t2
WHERE
(:BEN =1 OR (:BEN =0 AND t1.ENTRY_DATE=:DATE)
OR (:BEN =2 AND t1.DEPOSIT_DATE IS NOT NULL)
OR (:BEN =3 AND t1.DEPOSIT_DATE IS NULL)) AND
(:ALEX =1 OR (:ALEX =0 AND t1.ENTRY_DATE>=:DATE1 AND
t1.ENTRY_DATE<=:DATE2) OR (:ALEX =2 AND t1.DEPOSIT_DATE>=:DATE1
AND t1.DEPOSIT_DATE<=:DATE2))
AND T2.CLIENT_ID(+)=T1.CLIENT_ID
ORDER BY t1.SEC_CODE, t1.CHECK_CODE, fullName, t1.check_no
Please don't pay attention to the parameter names, it's a little funny for me but you guys won't be able to connect.
The first issue here is that even though some parameters are the same name, ADO sees them as individual parameters! So, if I do this:
checkload1->Parameters->ParamByName("BEN")->Value=0
ADO will not replace every occurrence of "BEN" with 0, and I end up with a result set of 0 records! Instead, I am using this:
checkload1->Parameters->Items[0]->Value = 0; // BEN param
checkload1->Parameters->Items[1]->Value = 0;
checkload1->Parameters->Items[3]->Value = 0;
checkload1->Parameters->Items[4]->Value = 0;
Basically, replacing every "BEN" parameter with 0 based on the parameter index.
This brings me results, but not right away.
So here is how it works: the application is a tree based user interface. There is a node that says "Today's Checks" and it displays today's checks when it is expanded. Great, now this works fantastic with BDE, and I only assign the parameter value once and it automatically replaces it wherever it sees "BEN", etc.
When using ADO components, I expand the "Today's Checks" node and the code runs though, loading the parameters, activating the query component and I get no results! So the node stays collapsed. If I click on the +
sign again to expand the tree, it loads the checks! And it will load them every time after that.
So, in the application there is a date option that defaults to today's date. If I change that to yesterday's date, I still get today's checks... It's like the parameters aren't getting updated. And if I try to start with a different date at the very beginning, I don't get any results! It will bring results with today's date, but after that it won't accept a different date.
I debugged the code and the dates are changing, but for some reason the parameters aren't changing. Here is my code block:
checkload1->Filter="" ;
checkload1->Filtered=false ;
switch(params)
{
case 0: checkload1->Parameters->Items[0]->Value = 1; // BEN param
checkload1->Parameters->Items[1]->Value = 1;
checkload1->Parameters->Items[3]->Value = 1;
checkload1->Parameters->Items[4]->Value = 1;
// ALEX Param
checkload1->Parameters->Items[5]->Value = 0;
checkload1->Parameters->Items[6]->Value = 0;
checkload1->Parameters->Items[9]->Value = 0;
checkload1->SQL->Strings[13] = "AND t1.CHECK_STATUS NOT IN ('Refunded', 'Posted') ";
break ;
case 1: checkload1->Parameters->Items[0]->Value = 0; // BEN param
checkload1->Parameters->Items[1]->Value = 0;
checkload1->Parameters->Items[3]->Value = 0;
checkload1->Parameters->Items[4]->Value = 0;
checkload1->Parameters->ParamByName("DATE")->Value=FormatDateTime("dd-mmm-yyyy", Date()) ;
checkload1->SQL->Strings[13] = " ";
break ;
case 2: checkload1->Parameters->Items[0]->Value = 2; // BEN param
checkload1->Parameters->Items[1]->Value = 2;
checkload1->Parameters->Items[3]->Value = 2;
checkload1->Parameters->Items[4]->Value = 2;
//ALEX param
checkload1->Parameters->Items[5]->Value = 2;
checkload1->Parameters->Items[6]->Value = 2;
checkload1->Parameters->Items[9]->Value = 2;
checkload1->SQL->Strings[13] = "AND t1.CHECK_STATUS IN ('Deposited') ";
break ;
case 3: checkload1->Parameters->Items[0]->Value = 3; // BEN param
checkload1->Parameters->Items[1]->Value = 3;
checkload1->Parameters->Items[3]->Value = 3;
checkload1->Parameters->Items[4]->Value = 3;
//ALEX param
checkload1->Parameters->Items[5]->Value = 0;
checkload1->Parameters->Items[6]->Value = 0;
checkload1->Parameters->Items[9]->Value = 0;
checkload1->SQL->Strings[13] = "AND t1.CHECK_STATUS IN ('Held') ";
break ;
}
if(!mainform->date1->Checked){
checkload1->Parameters->Items[5]->Value = 1;
checkload1->Parameters->Items[6]->Value = 1;
checkload1->Parameters->Items[9]->Value = 1;
}
checkload1->Parameters->Items[7]->Value = FormatDateTime("dd-mmm-yyyy", fromdate);
checkload1->Parameters->Items[10]->Value = FormatDateTime("dd-mmm-yyyy", fromdate);
checkload1->Parameters->Items[8]->Value = FormatDateTime("dd-mmm-yyyy", todate);
checkload1->Parameters->Items[11]->Value = FormatDateTime("dd-mmm-yyyy", todate);
if(filters != "") checkload1->SQL->Strings[12] = filters;
else checkload1->SQL->Strings[12]=" " ;
checkload1->Prepared = true;
checkload1->Active=true ;
Can someone with experience advise me on this?
I know this is ancient stuff, but those programs were written literally 15-20 years ago, and they are moving to a web-based user interface, but that's still being built. Until then, I need to make the required changes/updates as part of my job.
Okay I got this to work!!
For anyone out there who is struggling with BDE to work on Windows 7 64 bit, here is a solution! Remember the database I am dealing with is Oracle 8i and Borland C++ applications built with C++ Builder 6.
Follow the photo and arrows. I tried to put each photo with its own comment but then this site said I can't post more than 2 links... To hell with them so I put all on one picture.
This TQuery for example is looking for bnetdata as the database. Great, in the next picture we add an ADOConnection component
Click on connection string that's highlighted.
Choose use connection string and click on build.
Select the highlighted provider then click next.
Check use data source name then click the arrow to select one. Note that you will later enter the user name and password and check allow for saving password.
Select the same data source that the BDE components are using. Note that this is one of the sources under your system DSN in the ODBC Administrator. If it's not there, then create one.
Here is a shot from the ODBC Administrator. Note that this is still XP environment. You will need to create the same data source (bnetdata in my case) in the windows 7 machine.
Now click on advanced and check readwrite option from the list.
After you click OK on the ADOConnection component, as you see now in the object inspector. Look at the highlighted areas. Now, we need to set connected property to true. When you do that, it will ask you to log in to the database. Enter the user name and password and click OK. The connection property will now become true. After that you need to set the LoginPrompt property to false. Now click save on the project.
So let's say you have BDE database component too, click on it and then clear alias name and driver name and then put your database name under databaseName property (in my case it's bnetdata).
Save the project and compile in XP. Copy the application and paste it in Windows 7 machine and double click it and it will work! I have successfully converted all the applications to work on Windows 7. The hardest part was to get Borland installed and to get Windows 7 to recognize Oracle ODBC Driver under the Drivers tab in the ODBC Administrator.
Again, SQL Explorer that comes with Borland install is not going to work. So, I will still need to develop in my Windows XP VM but users can use the application in Windows 7 VM served as a terminal on a Windows server... Works for me!!
Hope this helps someone!
EDIT:
I also tried Microsoft OLE DB Provider for Oracle in the ADOConnection and it also worked. Didn't see a measurable impact on speed or performance. Both seem to perform the same way. I'm just surprised how adding the ADOConnection component allowed the application to connect to the database and work like it does in XP!
Also just to clear things up, you will not need to change the BDE components in the application. Only need to add the ADOConnection and all other components stay the same (BDE components). I was trying to convert to using ADO components but there is no need anymore.