@Override
  public void getFields( RowMetaInterface row, String name, RowMetaInterface[] info, StepMeta nextStep,
      VariableSpace space, Repository repository, IMetaStore metaStore ) throws KettleStepException {

    // Change all the fields to normal storage, this is the fastest way to handle lazy conversion.
    // It doesn't make sense to use it in the SCD context but people try it anyway
    //
    for ( ValueMetaInterface valueMeta : row.getValueMetaList() ) {
      valueMeta.setStorageType( ValueMetaInterface.STORAGE_TYPE_NORMAL );

      // Also change the trim type to "None" as this can cause trouble
      // during compare of the data when there are leading/trailing spaces in the target table
      //
      valueMeta.setTrimType( ValueMetaInterface.TRIM_TYPE_NONE );
    }

    // technical key can't be null

    if ( Utils.isEmpty( keyField ) ) {
      String message =
          BaseMessages.getString( PKG, "DimensionLookupMeta.Error.NoTechnicalKeySpecified" );

      logError( message );
      throw new KettleStepException( message );
    }

    ValueMetaInterface v = new ValueMetaInteger( keyField );
    if ( keyRename != null && keyRename.length() > 0 ) {
      v.setName( keyRename );
    }

    v.setLength( 9 );
    v.setPrecision( 0 );
    v.setOrigin( name );
    row.addValueMeta( v );

    // retrieve extra fields on lookup?
    // Don't bother if there are no return values specified.
    if ( !update && fieldLookup.length > 0 ) {
      Database db = null;
      try {
        // Get the rows from the table...
        if ( databaseMeta != null ) {
          db = createDatabaseObject();

          RowMetaInterface extraFields = getDatabaseTableFields( db, schemaName, tableName );

          for ( int i = 0; i < fieldLookup.length; i++ ) {
            v = extraFields.searchValueMeta( fieldLookup[i] );
            if ( v == null ) {
              String message =
                  BaseMessages.getString( PKG, "DimensionLookupMeta.Exception.UnableToFindReturnField",
                      fieldLookup[i] );
              logError( message );
              throw new KettleStepException( message );
            }

            // If the field needs to be renamed, rename
            if ( fieldStream[i] != null && fieldStream[i].length() > 0 ) {
              v.setName( fieldStream[i] );
            }
            v.setOrigin( name );
            row.addValueMeta( v );
          }
        } else {
          String message =
              BaseMessages.getString( PKG, "DimensionLookupMeta.Exception.UnableToRetrieveDataTypeOfReturnField" );
          logError( message );
          throw new KettleStepException( message );
        }
      } catch ( Exception e ) {
        String message =
            BaseMessages.getString( PKG, "DimensionLookupMeta.Exception.UnableToRetrieveDataTypeOfReturnField2" );
        logError( message );
        throw new KettleStepException( message, e );
      } finally {
        if ( db != null ) {
          db.disconnect();
        }
      }
    }
  }
@Test
  public void testGetFields() throws Exception {

    RowMeta extraFields = new RowMeta();
    extraFields.addValueMeta( new ValueMetaString( "field1" ) );

    DatabaseMeta dbMeta = mock( DatabaseMeta.class );

    DimensionLookupMeta meta = spy( new DimensionLookupMeta() );
    meta.setUpdate( false );
    meta.setKeyField( null );
    meta.setFieldLookup( new String[] { "field1" } );
    meta.setFieldStream( new String[] { "" } );
    meta.setDatabaseMeta( dbMeta );
    doReturn( extraFields ).when( meta ).getDatabaseTableFields( any(), anyString(), anyString() );
    doReturn( mock( LogChannelInterface.class ) ).when( meta ).getLog();

    RowMeta row = new RowMeta();
    try {
      meta.getFields( row, "DimensionLookupMetaTest", new RowMeta[] { row }, null, null, null, null );
    } catch ( Throwable e ) {
      Assert.assertTrue( e.getMessage().contains(
          BaseMessages.getString( DimensionLookupMeta.class, "DimensionLookupMeta.Error.NoTechnicalKeySpecified" ) ) );
    }
  }