Hi all!
Bug description:
LB version - 2.0 RC2 (my own trunk build)
Database - Oracle
Create script
CREATE TABLE AAAA (
COLUMN1 NUMBER(22,0) DEFAULT (0),
COLUMN2 NUMBER(22,0) DEFAULT 0
);
Table view
]
Name |
Type |
Nullable |
Default Value |
COLUMN1 |
NUMBER(22,0) |
Yes |
(0) |
COLUMN2 |
NUMBER(22,0) |
Yes |
0 |
ChangeSet view
Exception
java.sql.SQLException: ORA-01722: invalid number
Error executing SQL CREATE TABLE AAAA (COLUMN1 NUMBER(22,0) DEFAULT ‘(0)’ NOT NULL, COLUMN1 NUMBER(22,0) DEFAULT 0)
Code view [CreateTableGenerator.java (line 67)]
buffer.append(TypeConverterFactory.getInstance().findTypeConverter(database).getDataType(defaultValue).convertObjectToString(defaultValue, database));
There are two equals ways to set up columns default value in oracle. [don’t know how it relates to other sql-based-families]
- DEFAULT (0)
- DEFAULT 0
In both cases it will work as insertion ‘0’ number-type value into cell.
But in [1] Liquibase recognizes ‘(0)’ as VARCHAR2-type value, and then it wrapped it by [ ’ ].
Is it LB bug? or it’s just my trouble?
There is workaround fix - using xslt to change all default values [ (value) ] in my changeLog and cut brackets. But it’s uncomfortably.
In OracleTypeConverter class I found this method:
@Override
public Object convertDatabaseValueToObject(Object defaultValue, int dataType, int columnSize, int decimalDigits, Database database) throws ParseException {
if (defaultValue != null) {
if (defaultValue instanceof String) {
if (dataType == Types.DATE || dataType == Types.TIME || dataType == Types.TIMESTAMP) {
if (((String) defaultValue).indexOf("YYYY-MM-DD HH") > 0) {
defaultValue = ((String) defaultValue).replaceFirst("^to_date\\('","").replaceFirst("', 'YYYY-MM-DD HH24:MI:SS'\\)$","");
} else if (((String) defaultValue).indexOf("YYYY-MM-DD") > 0) {
defaultValue = ((String) defaultValue).replaceFirst("^to_date\\('","").replaceFirst("', 'YYYY-MM-DD'\\)$","");
} else {
defaultValue = ((String) defaultValue).replaceFirst("^to_date\\('","").replaceFirst("', 'HH24:MI:SS'\\)$","");
}
}
defaultValue = ((String) defaultValue).replaceFirst("'\\s*$", "'"); //sometimes oracle adds an extra space after the trailing ' (see http://sourceforge.net/tracker/index.php?func=detail&aid=1824663&group_id=187970&atid=923443).
}
}
return super.convertDatabaseValueToObject(defaultValue, dataType, columnSize, decimalDigits, database);
}
Is it right to add one more “else if” statement?
Something like that:
} else if (dataType == Types.INTEGER || dataType == Types.DECIMAL) {
defaultValue = ((String) defaultValue).replaceFirst("\\(", "").replaceFirst("\\)", "");
}
If it’s correct fix - I’ll commit it!
Also there should be included other non-char SQL types in this statement. Am I right?
That looks like a good fix to commit. You may want to check for other numberic types like Types.NUMBER, TINYINT, SMALLINT, BIGINT, FLOAT, REAL, etc.
Nathan
Ok, I fixed it.
P.S.
Sorry, I changed code-style in OracleTypeConverter class. That’s why it may looks like full-changed commit.
Another one bug
I’ll be post here other same-typed bugs…
There is a system property in Oracle table:
SYSTIMESTAMP
[description: http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/functions173.htm]
So, It may be used to setting up default value for date-typed column.
But LB again wrapped it like String value with ’ symbol (how it’s calling? [’] :))) )
CREATE TABLE AAAC
(
ID NUMBER(22,0) NOT NULL,
RECORD_TIME TIMESTAMP(6) DEFAULT 'SYSTIMESTAMP' NOT NULL
);
I’ll fix it tomorrow