Reputation: 434
I'm writing tools in java that connects to different access databases. I have a particular scenario that throws the following exception -5592:UCAExc:::4.0.4 precision or scale out of range
The exception is listed under HSQLDB exceptions:
5592=42592 precision or scale out of range
(so I know who generates it)
and according to this answer, this other answer, and the definitions in here, both precision and scale refer to characteristics of a double.
The exception occurs only when I use ucanaccess to connect to an old mdb (pre-access 2003) trhough a frontend database with linked tables to the mdb. However, ucanaccess can connect to the old mdb directly without any issue.
If I use the frontend in Access to modify the database it works fine, so I assume MS worked around the problem at least within Access.
My guess is that my ucanaccess connection is attempting to treat the database as a more modern one, being fooled by the front-end facade. But why this exception?
Minimal Complete Verifiable Example: Here is a minimal example to replicate the issue containing the offending mdb, is a gzip tarball which includes the following jar, the databases involved and a helpful readme file.
public static void main(String[] args) {
String query= "SELECT nombre FROM encemp where cveemp=1";
try {
Connection frontEndToAccdb = DriverManager.getConnection("jdbc:ucanaccess://FrontEndPointingToAccdb.accdb");
PreparedStatement statement = frontEndToAccdb.prepareStatement(query);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) System.out.println("Querying Accdb BackEnd through front end OK");
Connection directConnectionToMdb = DriverManager.getConnection("jdbc:ucanaccess://X:/BackendOld.mdb");
statement = directConnectionToMdb.prepareStatement(query);
resultSet = statement.executeQuery();
if (resultSet.next()) System.out.println("Querying mdb BackEnd directly OK");
//This is the one that will generate the exception
Connection frontEndToMdb = DriverManager.getConnection("jdbc:ucanaccess://FrontEndPointingToMdb.accdb");
statement = frontEndToMdb.prepareStatement(query);
resultSet = statement.executeQuery();
if (resultSet.next()) System.out.println("Querying mdb BackEnd through front end OK");
} catch (SQLException ex) {
System.out.printf("%s:%s\n", ex.getErrorCode(),ex.getMessage());
}
I've been struggling navigating the DatabaseMetaData and still have no clue why the offending mdb is generating the exception.
Upvotes: 2
Views: 1408
Reputation: 123779
As it turns out, this particular issue has nothing to do with DECIMAL numbers, or numeric columns at all. It is a bug in UCanAccess caused by a bug in Jackcess where the width of an Access_97 TEXT field is mis-reported as half of its actual width.
The database in question has a table with a column defined as TEXT(1), so Jackcess getLengthInUnits
reports zero (because of integer division). UCanAccess tries to create a table in the HSQLDB backing database as
CREATE CACHED TABLE DETCAD(SERIE VARCHAR(0), ...
and the VARCHAR(0)
is triggering the "precision or scale out of range" exception.
jackcess-2.2.2.jar fixes the issue. You can use it to replace the jackcess-2.1.11.jar file that ships with UCanAccess 4.0.4.
Upvotes: 2
Reputation: 121759
I took the liberty of updating your title. Hopefully the new wording conveys what you mean.
Please do the following:
a) Query the column definitions in question directly. For example:
// GetMetaData():
try (ResultSet rsMD = connChem.getMetaData().getTables(null, null, null, null)) {
while (rsMD.next()) {
String tblName = rsMD.getString("TABLE_NAME");
System.out.println(tblName);
}
}
... or ...
-- SQL "select" from MSysObjects
SELECT Name
FROM MSysObjects
WHERE Left([Name],1)<>"~"
AND Left([Name],4)<>"MSys"
AND Type In (1,4,6)
ORDER BY Name;
b) Compare the DB column definitions (above) with the corresponding Hibernate class members (for example, in your favorite IDE).
c) Compare the results for an "old" .mdb (which "works") vs. a "new" .accdb.
Please update your post with the results.
Upvotes: 3
Reputation: 25132
Precision is the maximum total number of digits in a decimal. Scale is the number of digits to the right of the decimal point (ref). So if you had decimal(20,10)
then it would be a decimal with 10 digits to the left, and 10 digits to the right of the decimal for a total of 20 digits. i.e. 1234567890.1234567890
. The maximum precision is 38, default is 18.
Examples
decimal(38,0): '12345678912345678912345678912345678900'
decimal(38,1): '1234567891234567891234567891234567890.0'
decimal(38,2): '123456789123456789123456789123456789.00'
decimal(38,3): '12345678912345678912345678912345678.900'
decimal(10,8): '12.12345678'
Upvotes: 2