0

I am supporting an ASP classic application that uses ADODB.Recordset objects to interact with an Oracle database through an ODBC connection. The application works as desired in our QA environment, but we are encountering problems using the Recordset.Delete and Recordset.Update functions in our production environment. I'm describing the Recordset.Delete scenario below because it is simpler to explain, but the Update scenario is similar.

My question is: whether anyone can explain the problematic behavior or can suggest ways to address it.


The following code is a slightly redacted extract from a procedure that allows the user to select and delete a record from any one of a number of tables.

Dim dbConnection
Dim objRS
Dim table
Dim filter_key

Set dbConnection = openDBConnection()
filter_key = Request.Form("pk")
table = getValidTableName(Request.Form("table"))
Set objRS = Server.CreateObject("ADODB.Recordset")

objRS.Open table, dbConnection, , adLockOptimistic, adCmdTable
objRS.Filter = filter_key
objRS.Delete

The target table and the record to be deleted are passed in the "table" and "pk" form parameters. For example, they could be defined as

  • table: PERSON
  • pk: person_id = 12345

This code works as desired in QA. The objRS.Delete line fails in production with the error

80004005|[Oracle][ODBC]Wrong_number_of_parameters

The Oracle client is the same in both environments, but the msado15.dlls containing the ADODB.Recordset have slightly different versions: QA - 10.0.14393.4169, Prod - 10.0.17763.1697. My current hypothesis is that the version difference explains the difference in behavior and accounts for the errors in production.

I've enabled ODBC tracing, and while I'm not positive that I'm intepreting the output correctly, it seems like the generated DELETE statement includes a WHERE clause that is not limited to the simple clause assigned as a filter_key (e.g. WHERE person_id = 12345). Instead, the WHERE clause appears to include every column in the target table, as in

WHERE (LAST_NAME=? AND FIRST_NAME=? AND ...

In QA, the parameter values are all being bound properly. In production, it seems like there are calls to bind each parameter value, but the calls fail to increment the ParameterNumber properly (ParameterNumber described here - https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlbindparameter-function?view=sql-server-ver16). That is, it appears that there are multiple calls to bind different values, but each call binds the value to ParameterNumber 1, leaving the remaining parameters unbound.


Again, I'm not positive that the interpretation above is correct. If so, this seems like a bug. However, I don't know ASP or ADODB well enough to know if instead the application is doing something wrong, so any pointers would be appreciated.

easleyfixed
  • 219
  • 1
  • 13
jjw
  • 111
  • 7
  • 1
    If all else is the same, I'd start by trying to find out where the variance in DLL's is coming from. I'd even try copying the DLL manually (with backup of course) so both environments are the same. – mxmissile Jul 07 '23 at 15:34
  • @mxmissile Thank you. From what I understand, the DLL is distributed along with the OS, and the OS version is also different between the two environments (not ideal, I realize). I've been starting to try the experiment you described, but so far my attempts to unregister the existing DLL version on QA and replace it with the one from production have been failing. Even so, it's a good suggestion and I'm going to keep poking at it. – jjw Jul 07 '23 at 15:47
  • Ugh, I totally forgot about having to register DLLs, its been years since I've worked with legacy asp. And now I distinctly remember going down that rabbit hole several times! I dont remember, but can't you just execute raw SQL? If all else fails that could be your fallback. – mxmissile Jul 07 '23 at 15:51
  • That would also work. In fact, it does work throughout the rest of the application. The difficulty in doing that in this case is that the procedure is intended to support something like a "generic - update any table content" functionality. That is, it needs to be flexible enough to support many tables, making it tedious to code the raw SQL for each of the potential targets. I'm not a big fan of the design and might not have implemented it, but for now, we're stuck with it. At this point, what you've suggested is our fallback though. – jjw Jul 07 '23 at 15:54
  • Good luck! I don't envy you at all. Sorry I was not much help. – mxmissile Jul 07 '23 at 15:58
  • Which ODBC driver do you use? – Wernfried Domscheit Jul 08 '23 at 03:57
  • We're using the Oracle 19 instant client (which includes the ODBC driver) - version 19.0.0. – jjw Jul 10 '23 at 11:50

0 Answers0