Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DBUnit PostgresqlDataTypeFactory does not recognizes enum list

I'm using DBUnit for an integration test, and before executing the test code I'm running into this error:

badges.track_types data type (2003, '_text') not recognized and will be ignored. See FAQ for more information.

org.dbunit.dataset.NoSuchColumnException: badges.TRACK_TYPES -  (Non-uppercase input column: track_types) in ColumnNameToIndexes cache map. Note that the map's column names are NOT case sensitive.

the column that is ignored is a list of enums. In the dataset it's written like this :

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  // More info ...
  <badges name="30&apos;000" description="30k a day" image_name="30000.png" threshold_val="30000.00000000" has_many="true" id="45" track_types="{TRACK_GENERIC}" "/> 
</dataset> 

I looked in the DBUnit FAQ and saw this issue , that says that I have to override the isEnumType() method to support my enum is Postgresql, so I did this:

/**
 * Override method to set custom properties/features
 */
protected void setUpDatabaseConfig(DatabaseConfig config) {

    config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new PostgresqlDataTypeFactory(){
        public boolean isEnumType(String sqlTypeName) {
            if(sqlTypeName.equalsIgnoreCase("track_types")){
                return true;
            }
            return false;
        }
    });
    config.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new DefaultMetadataHandler());
}

But I still get the same error, and I don't know why. Maybe I'm not overriding well the method? Maybe it's not even the cause of my problem? If you need any other code just ask, thanks!

like image 637
alfizqu Avatar asked Jun 23 '16 11:06

alfizqu


3 Answers

Try to persist the enum with its value

enum.values();

it return an array than you save this element

like image 143
Irazza Avatar answered Nov 14 '22 22:11

Irazza


Well... I wasn't able to solve this exactly but managed to solve it by a workaround.

This error comes because of the @DatabaseSetup annotation. If I did this process without using it, it still throws a 'column not recognized' error, because it doesn't recognize postgres arrays (that was the root cause that I have) but I could solve it by creating a new DataTypeFactory that extends from the default one:

public class PsqlArrayDataTypeFactory extends DefaultDataTypeFactory {
        public DataType createDataType(int sqlType, String sqlTypeName) throws DataTypeException {
            if (sqlType == Types.ARRAY)
            {
                return DataType.VARCHAR;
            }

            return super.createDataType(sqlType, sqlTypeName);
        }
    }
like image 31
alfizqu Avatar answered Nov 14 '22 22:11

alfizqu


I had next error:

Caused by: org.postgresql.util.PSQLException: ERROR: column "status" is of type topic_status but expression is of type character varying
  Hint: You will need to rewrite or cast the expression.

DbUnit requests meta for table and receives a type VARCHAR for enums from PostgreSQL. But PostgreSQL won't accept this type back.

I overrode methods from PostgresqlDataTypeFactory in next way:

config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, 
    new PostgresqlDataTypeFactory() {
        @Override
        public boolean isEnumType(String sqlTypeName) {
            return "topic_status".equalsIgnoreCase(sqlTypeName);
        }

        @Override
        public DataType createDataType(int sqlType, String sqlTypeName) throws DataTypeException {
            if (isEnumType(sqlTypeName)) {
                sqlType = Types.OTHER;
            }
            return super.createDataType(sqlType, sqlTypeName);
        }
    });
);

This sets type for enum as OTHER and parent method super.createDataType(sqlType, sqlTypeName) creates DataType in proper way.

PostgreSQL version: 9.6.5
DbUnit version: 2.5.4

More information could be found on discussion.

like image 21
dlopatin Avatar answered Nov 14 '22 23:11

dlopatin