DbUnit Support

Please ask your questions in the DbUnit user mailing list. Questions posted there are usually answered promptly.

Question written here may not be answered in a timely manner.

BuildingDbUnit | SupportedRDBMS | PendingDbUnitFaq | ChangesSinceLastRelease


Question:
I use apache-ant-1.6.1 with DBUNIT 2.0 and Oracle 9.2
and some tables have 'FLOAT' type fields.

I have the following error

[dbunit] Executing operation: CLEAN_INSERT
   [dbunit]           on   file: D:\zzz\data\ZZZ_TESTF.data.xml
   [dbunit]           with format: null
   [dbunit] WARNING - ADMCHS.F101 data type (1111, �FLOAT�) not recognized and will be ignored. See FAQ for more information.
   [dbunit] WARNING - ADMCHS.F100 data type (1111, �FLOAT�) not recognized and will be ignored. See FAQ for more information.
   [dbunit] WARNING - ADMCHS.FS02 data type (1111, �FLOAT�) not recognized and will be ignored. See FAQ for more information.
   ...
BUILD FAILED
D:\zzz\build\build.xml:206: org.dbunit.dataset.NoSuchColumnException: ADMCHS.F100

The field is rejected because of the type FLOAT, and after that the field is missing.

I used the attribute datatypeFactory="org.dbunit.ext.oracle.OracleDataTypeFactory"
but it's unchanged ( it doesn't works ).

Do you have a idea ?

Thanks.

Renaud Vernet (May 28, 2004)

Answer:
Seems that Oracle FLOAT support is missing in DbUnit 2.0. DbUnit 2.1 now supports Oracle FLOAT via OracleDataTypeFactory. —ManuelLaflamme (May 31, 2004)

Thanks:
It's Ok, it works with DbUnit 2.1

( and datatypeFactory="org.dbunit.ext.oracle.OracleDataTypeFactory" ).

Thank you.

Renaud Vernet (June 1, 2004)


Hi,

I'm using Oracle 7, 8 and 9.
How do I tell dbUnit explicitly which Oracle sequence to use for a given table and a given column?
I understand that you can override PKs by providing values in the xml file. But I want Oracle to generate them for me automatically using its sequences. This seems to work for MS SQL Server but not for Oracle.

EG: "myTable" has 2 columns: "foo" and "Id" (PK)

my xml file contains this:

<dataset>
   <MYTABLE FOO="HELLO"/>
  </dataset>

my DTD contains this:

<!ELEMENT MYTABLE EMPTY>
  <!ATTLIST MYTABLE
    FOO CDATA #REQUIRED
    ID CDATA #IMPLIED
  >
  <!ELEMENT dataset (MYTABLE*)>

When running my test, I get an Oracle exception saying that null is not an acceptable value for the PK (and of course it isn't!).

I took a look at the dbUnit source code, but I didn't find anything that was close to "SELECT mysequence.nextval FROM dual". Did I overlook something?


[oct 27, 2004]

Hi,

This is a followup to my previous post.

I spend a couple of hours reading the dbUnit docs/facs/wikis and source code trying to figure out how to use Oracle sequences, but unless I overlooked something, I think this is not possible with the current implementation.

So I took some extra time to find a workaround to insert Oracle sequence generated IDs into dbUnit's datasets, muchlike what ReplacementDataSet does. I subclassed DatabaseTestCase already earlier in a abstract class (AbstractDatabaseTestCase) to be able to use a common connection in case of insertion of my testcases in a testsuite. But I added the following code just now. It looks up the first row of each table in the dataset to determine which columns need sequence replacement. The replacement is done on the "${…}" expression value.

This code is "quick and dirty" and surely needs some cleanup and tuning.

Anyways, this is just a first try. I'll post further improvements as I go, if this can be of any help to anyone.

Stephane Vandenbussche

private void replaceSequence(IDataSet ds) throws Exception {
    ITableIterator iter = ds.iterator();
    // iterate all tables
    while (iter.next()) {
      ITable table = iter.getTable();
      Column[] cols = table.getTableMetaData().getColumns();
      ArrayList al = new ArrayList(cols.length);
      // filter columns containing expression "${...}"
      for (int i = 0; i < cols.length; i++) {
        Object o = table.getValue(0, cols[i].getColumnName());
        if (o != null) {
          String val = o.toString();
          if ((val.indexOf("${") == 0) && (val.indexOf("}") == val.length() - 1)) {
            // associate column name and sequence name
            al.add(new String[]{cols[i].getColumnName(), val.substring(2, val.length()-1)});
          }
        }
      }
      cols = null;
      int maxi = table.getRowCount();
      int maxj = al.size();
      if ((maxi > 0) && (maxj > 0)) {
        // replace each value "${xxxxx}" by the next sequence value
        // for each row
        for (int i = 0; i < maxi; i++) {
          // for each selected column
          for (int j = 0; j < maxj; j++) {
            String[] field = (String[])al.get(j);
            Integer nextVal = getSequenceNextVal(field[1]);
            ((DefaultTable) table).setValue(i, field[0], nextVal);
          }
        }
      }
    }
  }

  private Integer getSequenceNextVal(String sequenceName) throws SQLException, Exception {
      Statement st = this.getConnection().getConnection().createStatement();
      ResultSet rs = st.executeQuery("SELECT " + sequenceName + ".nextval FROM dual");
      rs.next();
      st = null;
      return new Integer(rs.getInt(1));
  }

My AbstractDatabaseTestCase class has a boolean flag "useOracleSequence" which tells the getDataSet callback method to call replaceSequence.

I can now write my xml dataset as follows :

<dataset>
   <MYTABLE FOO="Hello" ID="${MYTABLE_SEQ}"/>
   <MYTABLE FOO="World" ID="${MYTABLE_SEQ}"/>
   <OTHERTABLE BAR="Hello" ID="${OTHERTABLE_SEQ}"/>
   <OTHERTABLE BAR="World" ID="${OTHERTABLE_SEQ}"/>
  </dataset>

where MYTABLE_SEQ is the name of Oracle sequence to be used.


Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License