How do you coerce float values in MySQL for classic ASP scripts? - mysql

I have been charged with maintaining a legacy classic ASP application. The application uses an ODBC system DSN to connect to a MySQL database.
We had to recently update the servers to satisfy some licencing requirements. We were on Windows, with MySQL 4.x and the 3.51 ODBC driver. We moved to a Linux machine running MySQL 5.1.43 and are running the 5.1.6 ODBC driver on the new IIS server.
Users almost instantly started reporting errors as such:
Row cannot be located for updating.
Some values may have been changed
since it was last read.
This is a ghost error, and the same data changes, on the same record, at a different time won't always produce the error. It is also intermittent between different records, as in, sometimes, no matter what values I plug in, I haven't been able to repro the defect on all records.
It is happening across 70 of about 120 scripts, many over 1,000 lines long.
The only consistency I can find is that on all of the scripts that fail, they are all reading/writing floats to the DB. Fields that have a null value don't seem to crash, but if there is a value like '19' in the database (note the no decimal places) that seems to fail, whereas, '19.00' does not. Most floats are defined as 11,2.
The scripts are using ADODB and recordsets. Updates are done with the following pattern:
select * from table where ID =
udpdated recordID
update properties of the record from the form
call RecordSet.Update and RecordSet.Close
The error is generated from the RecordSet.Update command.
I have created a workaround, where rather than select/copy/update I generate an SQL statement that I execute. This works flawlessly (obviously, an UPDATE statement with a where clause is more focused and doesn't consider fields not updated), so I have a pretty good feeling that it is a rounding issue with the floats that is causing a mis-match with the re-retrieval of the record on the update call.
I really would prefer NOT re-writing 100's of these instances (a grep across the source directly finds 280+ update calls).
Can anyone confirm that the issue here is related to floats/rounding?
And if so, is there a global fix I can apply?
Thanks in advance,
-jc

Have a look at MySQL Forums :: ODBC :: Row cannot be located for updating.
They seem to have found some workaround and some explanations as well..

I ran into a similar issue with a VBA macro utilizing 4.1. When upgraded to 5 errors started popping up.
For me the issue was that values being returned to VBA from MySQL was in a unhandled (by VBA) decimal format.
A CAST on the numbers when querying helped to fix the issue.
So for your issue perhaps the ODBC/ASP combination is recording/reading values differently then what you might expect them to be.

Related

ODBC call failed - Random date overflow errors after moving from 32-bit ODBC 5.1 to 64-bit 5.3

Background:
Legacy code running in MS Access 2003.
Sqls run by CurrentDB in Access.
Currently running on Windows 7 32-bit machine.
Connecting to MySQL Server 5.5 through a ODBC 5.1 Driver.
Problem:
Trying to migrate to Windows server 2012 64 bit.
ODBC 5.3 Unicode Driver (32 bit).
Don't want to use time rewriting everything as there is a lot of code, and it will in a not to distant future be removed.
Issue:
Several sql statements fail when running on the new servers. Worked on old servers.
All the failed sqls have now() in the statement.
Error description says ODBC call failed. While the more detailed description says date overflow - "[MySQL][ODBC 5.3(w) Driver][mysqlid-5.5.28-log]Date overflow".
Happens randomly, and when it happens and Access stops one can usually just choose continue and the sql will then work. It fails less than 1% of the times it runs (of thousands).
The only dates in the sql are in the where clause: "and fieldA > now()", where fieldA is a datetime column. This is a get recordset sql. Another error during an insert is the same, but where an integer was subtracted from now() before compared to a datetime.
I don't understand why it says date overflow when there doesn't seem to be a reason for the time of either datetime or "now" to be removed? And since the datetime field is already in the database and now() will get current date and time there shouldn't be any invalid dates?
Any help in what the problem might be or how to debug/log anything that might help would be highly appreciated.
Turning trace on in the ODBC driver is not an option because it happens so randomly, there is so much traffic therefore this would slow down everything such that nothing happens.
Note that I also did encounter one sql where the date overflow error message was correct. It seems that prior to 5.3 when inserting a datetime into a date field it was automatically truncated, because a sql which had been successfull 3000 times started failing. Therefore this sql has been fixed by extracting the date from the field first. But the other errors must be something different.
New version containing a bugfix has been released by Oracle: 5.3.8
This error was a bug that seems to have been introduced in version 5.1.11.
In advanced options there is now a Date overflow check box which has to be ticked for the code to continue when there is an error.
Reply from Oracle about the fix:
"For your information the fix approach was that in C or C++ it is possible to read or write DATE type using SQL_TIMESTAMP_STRUCT.
This struct can hold both date and time.
The error (Date overflow) was generated when with operations that are supposed to be DATE-only this struct got non-zero values for time.
That is the canonical approach as ODBC API requires, however, it causes inconveniences sometimes when for instance the app did not bother
to initialize the whole structure with 0 values because it knows it will only need the DATE part but the random values for TIME fraction could cause the errors despite of being truncated.
A new option was introduced to continue with the query execution rather then return error.
The server will ignore the TIME part and the result is the same as if there were zeroes."
This appears to be an issue with MySQL Connector/ODBC versions 5.2 and later. A web search led to this thread on another site, which in turn led to this unresolved bug report. Note that this is a broader MySQL Connector/ODBC issue; it is not specific to Access applications.
MySQL Connector/ODBC 5.1.13 is still available for download, so your most expedient solution would probably be to simply use that version until the code in question is taken out of service. Your other alternatives might include:
using a newer version of MySQL Server (with [better?] support for fractional seconds), or
tweaking the Access SQL queries to use something other than the Now() function (which you, understandably, would like to avoid).
I had exactly the same problem - "Date overflow" error when saving the data in an Access form.
I changed the data type from "datetime" to "timestamp" in the linked MySQL table and this solved the issue. The datetime data type seems to be too short to accommodate the value of Now() in MS Access.
Remember to refresh the linked tables in Access afterwards.
I also noticed that there was a "Not Null" tick mark next to the ModifyTime timestamp field in the MySQL table. I unticked this.
After these two changes I no longer get the Date Overflow error when Me.Dirty=False executes in Access.
I use Access365 (x64), MySQL ODBC Connector 8.0.31 (x64) and MySQL 5.6

Why don't date functions work as defaults in MS Access used with MySQL

I am converting a Large MS Access 2010 application to act as a front end to MySQL 5.5 database, via the v5.1 ODBC Connector, and I am experiencing a strange problem when inserting new records with bound data forms.
In a data-entry form, if the default value of a date field is set in the properties of the control as a constant (such as #04-01-2014#) the new record is created in MySQL successfully, and after saving, all fields are visible in their associated bound fields. But if the default value is defined in the Access control as a function (example: =Date()) then although the MySQL row is created successfully, ODBC fails to find the new row and Access displays all values as #DELETED. Refresh and/or requery commands are not helpful. This is nothing to do with the well known issue of -- must have a primary key and a datestamp in MySQL. All of these safeguards are in place, and as stated, it does work without FE defaults.
No defaults are being set in the MySQL backend, and it makes no difference whether or not Nulls are allowed. Data type used in the backend is DateTime. If I do set defaults in the BE and none in the FE, everything is fine. But that way, the user DOES NOT SEE THE DEFAULTS in the data entry form... an unacceptable situation.
I have also tested both ODBC v5.2, and MySQL 5.6 with exactly the same results.
A solution that seems to work (so far) is to set all defaults in code, in the form.beforeUpdate event. Something like this:
form_beforeUpdate()
if me.newrecord then
field1.value = date()
field2.value = fOtherDate()
'etc
end if
'other code
exit sub
I could insert all new records with unbound forms and passthrough queries. But with 75,000 lines of code, that is a very big job
My question is - why do I need these "workarounds"? Isn't the whole purpose of ODBC to allow fairly normal operation? What is it about simple functions that "breaks it"? What other "ordinary" Access methods will break it? If I don't understand why it didn't work I can't be sure it is properly fixed.
Has anyone else had any experience with this SPECIFIC issue? I could not find any reference to it elsewhere. Thank you for your time.

Informix + SQLAlchemy looking for table that doesn't exist

I'm trying to connect to an Informix database with SQLAlchemy. All my tests seem to show the connection is working; however, whenever I try and perform a read of the database I get the error:
DatabaseError: (DatabaseError) SQLCODE -217 in PREPARE:
IX000: Column (current_role) not found in any table in the query (or SLV is undefined).
'select CURRENT_ROLE from systables' ()
Now the database that I am connecting to doesn't have CURRENT_ROLE, so how can I get round this?
My interactive traceback of the error is shown below in a gist:
https://gist.github.com/2157378
The offending line is:
File "build/bdist.linux-i686/egg/sqlalchemy/dialects/informix/base.py", line 593, in _get_default_schema_name
return connection.execute('select CURRENT_ROLE from systables').scalar()
Is there any workaround for this problem?
I am now led to believe this is a bug in SQLAlchemy (after talking to users in #sqlalchemy) and I have filed a bug report:
http://www.sqlalchemy.org/trac/ticket/2448
You've not identified which version of IBM Informix Dynamic Server (IDS) you are using or which platform you are using it on, so it is hard to help you.
It appears that SQLAlchemy expects a more recent version of Informix than you are using. Somewhat to my surprise, the niladic function CURRENT_ROLE appears to be available in IDS 11.70 (tested on 11.70.FC4 on RHEL 5 for x86/64). It was not recently added, so it will be in any 11.70 version, and possibly in some earlier versions (but not as early as the version you are using).
I'm not sure how much of a bug it is in SQLAlchemy. If the version of Informix that you're using is really old, there is limited virtue in them adding support for it. You can find out which version you're using by running:
SELECT DBINFO('version', 'full')
FROM 'informix'.systables
WHERE tabid = 1;
If that doesn't work, you are many years out of date with your server.
Addendum
Thinking about it a bit more...I wonder what SQLAlchemy is going to do with the role. It probably shouldn't be trying to analyze whether you have permission; it should try an operation and deal with failures. That will be quicker, especially in the common case where you actually do have permission.
There could be two issues:
SQLAlchemy should be aware that some (as yet indeterminate) list of old versions of IDS do not support CURRENT_ROLE.
SQLAlchemy should review why it needs to be aware of the current role.

SSIS: SQL 2008 R2 to MySQL data loss

I have an SSIS package set up to export data from a SQL Server 2008 R2 table to a MySQL version of that table. The package executes however, I am getting about 1% of the rows failing to be exported.
My source connection uses the SQL statement
SELECT * FROM Table1
all of the columns are integers. An example of a row which is exported successfully is
2169,2680, 3532,NULL, 2169
compared to a row which fails
2168,2679,3532,NULL, 2168
virtually nothing different that I can ascertain.
Notably, if I change the source query to only attempt the transfer of a single failing row - ie.
SELECT * FROM Table1 WHERE ID = 2168
then the record is exported fine - it is only when part of a select which returns multiple rows that it fails. The same rows fail the export each time. I have redirected error rows to a text file which displays a -1071610801 error for the failing rows. This would apparently translate to:-
DTS_E_ADODESTERRORUPDATEROW: "An error has occurred while sending this row to destination data source."
which doesn't really add a great deal to my understanding of the issue!
I am wondering if there is a locking issue or something preventing given rows from being fetched or inserted correctly but if anyone has any ideas or suggestions on what might be causing this or even better how to go about resolving it they would be greatly appreciated. I am currently at a total loss...
Try to setup longer timeout (1 day) ot the mysql (ADO.NET) destination.
Well after much head scratching and attempting every work around that I could come up with I have finally found a solution for this.
In the end I switched out the MySQL connector for a different driver produced by devArt -dotConnect for MySql and, with a few minor exceptions (which I think I can resolve) all of my data is now exporting without error.
The driver is a paid for product unfortunately but in the end I'd have taken out a new mortgage to see all those tasks go green!

Write Conflict messages suddenly start happening in ODBC linked tables

I have a mySQL database that tracks our projects and drives our website's display of their info. For ease of updating the database I have set up an access database that used an ODBC connection (MySQL ODBC 5.1) to edit the data. It has been working just fine for the past few months with no hiccups.
However, last night users(2 of 3) experienced Write Conflict errors. The users could only Copy the changes to the Clipboard or Drop the changes. So thinking there is something wrong with the Access database I created a new access database, linked the tables through the ODBC connection, and still the issue occurred. I also deleted and recreated the ODBC connection, to no effect.
So where do I go from here? What could have caused this issue to crop up now, not when I was setting this up months ago?
There have been no changes to the database server, database or access database in the last week (+5 days).
We have made sure that only one instance of Access is attempting to effect the database.
All tables have a PK and a timestamp column.
We are not using any forms, just using the Table interface.
The server has not been updated, nor has the ODBC connection.
We are using Access 2007
Nothing is showing up in the server's error log when we try and update rows.
In general, all ODBC databases used from Access need to have PKs in all tables and timestamp fields in them that are updated each time the record is changed. Access uses this in bound forms for handling refreshes of the bound data and Jet uses them in in choosing how to tell the ODBC database what do update.
You may be able to get things to work with some tables without PK and timestamp, but I've found that it's best just to make sure that all your tables have them so you don't run into the problem (I never have any tables with no PK, of course).y
Make sure BIT columns have default values that are not NULL. Any records which have a BIT column set to NULL could get the Write Conflict error.