The Derby reference guide says for decimal data types:

  The precision must be between 1 and 31. The scale must be less than
  or equal to the precision.

And indeed, if I try to create a table with precision of 32 or more, I get an 
error:

ij> connect 'mydb;create=true';
ij> create table oops (d decimal(32, 0));
ERROR 42X48: Value '32' is not a valid precision for DECIMAL.

But it is nonetheless possible to create a decimal value in Derby that has a precision larger than 32. Esp. via a VALUES statement:

-- Following constant has 44 digits...
ij> values 12345678901234567890123456789012345678901234;
1
---------------------------------------------
12345678901234567890123456789012345678901234

1 row selected

Should the above VALUES clause throw an error, or is this intentional (and correct) behavior? If it's intentional and correct, then I think this causes problems for the new (to 10.3) CREATE TABLE AS <subquery> WITH NO DATA functionality. For example, since the above VALUES clause executes without error, the following statement suceeds in Derby 10.3:

ij> create table invalid_t (d) as
  values 12345678901234567890123456789012345678901234 with no data;
0 rows inserted/updated/deleted

If we describe the new table, we can see that the precision is set to 44:

ij> describe invalid_t;
COLUMN_NAME         |TYPE_NAME|DEC&|NUM&|COLUM&|COLUMN_DEF|CHAR_OCTE&|IS_NULL&
------------------------------------------------------------------------------
D                   |DECIMAL  |0   |10  |*44*  |NULL      |NULL      |NO

And we are now allowed to insert values with precision 44 (or less) into that 
table:

ij> insert into invalid_t values 12345678901234567890123456789012345678901234;
1 row inserted/updated/deleted

Further, we can correctly select the decimal column from that table without error or loss of precision:

ij> select d from invalid_t;
D
---------------------------------------------
12345678901234567890123456789012345678901234

1 row selected

But if we use the column in a numeric expression, we get an error saying that the resultant value is out of range:

ij> select d * 1 from invalid_t;
1
--------------------------------
ERROR 22003: The resulting value is outside the range for the data type DECIMAL/NUMERIC(31,0).

ij> select d / 2 from invalid_t;
1
--------------------------------
ERROR 22003: The resulting value is outside the range for the data type DECIMAL/NUMERIC(31,0).

ij> select d + 2 from invalid_t;
1
--------------------------------
ERROR 22003: The resulting value is outside the range for the data type DECIMAL/NUMERIC(31,0).

ij> select d - 1 from invalid_t;
1
--------------------------------
ERROR 22003: The resulting value is outside the range for the data type DECIMAL/NUMERIC(31,0).

Note that if the expression returns a decimal with precision less than 32, then all is okay:

ij> select d / 234567898765432 from invalid_t;
1
--------------------------------
52631579027700853983831737804

1 row selected

If we run dblook against the database the column does indeed have a precision 
of 44:

> java org.apache.derby.tools.dblook -d jdbc:derby:mydb -t invalid_t -verbose

-- ----------------------------------------------
-- DDL Statements for tables
-- ----------------------------------------------

CREATE TABLE "APP"."INVALID_T" ("D" DECIMAL(44,0) NOT NULL);

But as expected, trying to execute the generated DDL will lead to an error:

ij> connect 'diffdb;create=true';
ij> CREATE TABLE "APP"."INVALID_T" ("D" DECIMAL(44,0) NOT NULL);
ERROR 42X48: Value '44' is not a valid precision for DECIMAL.

I'm pretty sure this warrants a Jira, but I'm not real sure where the bug is. Should the VALUES clause be throwing an error? Or should the CREATE TABLE AS ... WITH NO DATA functionality be responsible for checking the column definition? Or is the problem someplace else entirely?

Army

Reply via email to