public void getFields(
      RowMetaInterface row,
      String name,
      RowMetaInterface[] info,
      StepMeta nextStep,
      VariableSpace space)
      throws KettleStepException {

    if (databaseMeta == null) return;

    Database db = new Database(databaseMeta);
    databases = new Database[] {db}; // Keep track of this one for cancelQuery

    // First try without connecting to the database... (can be  S L O W)
    // See if it's in the cache...
    RowMetaInterface add = null;
    String realSQL = sql;
    if (replacevars) realSQL = space.environmentSubstitute(realSQL);
    try {
      add = db.getQueryFields(realSQL, false);
    } catch (KettleDatabaseException dbe) {
      throw new KettleStepException(
          Messages.getString("DynamicSQLRowMeta.Exception.UnableToDetermineQueryFields")
              + Const.CR
              + sql,
          dbe); //$NON-NLS-1$
    }

    if (add != null) // Cache hit, just return it this...
    {
      for (int i = 0; i < add.size(); i++) {
        ValueMetaInterface v = add.getValueMeta(i);
        v.setOrigin(name);
      }
      row.addRowMeta(add);
    } else

      // No cache hit, connect to the database, do it the hard way...
      try {
        db.connect();
        add = db.getQueryFields(realSQL, false);
        for (int i = 0; i < add.size(); i++) {
          ValueMetaInterface v = add.getValueMeta(i);
          v.setOrigin(name);
        }
        row.addRowMeta(add);
        db.disconnect();
      } catch (KettleDatabaseException dbe) {
        throw new KettleStepException(
            Messages.getString("DynamicSQLRowMeta.Exception.ErrorObtainingFields"),
            dbe); //$NON-NLS-1$
      }
  }
  public void check(
      List<CheckResultInterface> remarks,
      TransMeta transMeta,
      StepMeta stepinfo,
      RowMetaInterface prev,
      String[] input,
      String[] output,
      RowMetaInterface info) {
    CheckResult cr;
    String error_message = ""; // $NON-NLS-1$

    // See if we have input streams leading to this step!
    if (input.length > 0) {
      cr =
          new CheckResult(
              CheckResult.TYPE_RESULT_OK,
              Messages.getString("DynamicSQLRowMeta.CheckResult.ReceivingInfo"),
              stepinfo); //$NON-NLS-1$
      remarks.add(cr);
    } else {
      cr =
          new CheckResult(
              CheckResult.TYPE_RESULT_ERROR,
              Messages.getString("DynamicSQLRowMeta.CheckResult.NoInputReceived"),
              stepinfo); //$NON-NLS-1$
      remarks.add(cr);
    }

    // Check for SQL field
    if (Const.isEmpty(sqlfieldname)) {
      cr =
          new CheckResult(
              CheckResult.TYPE_RESULT_ERROR,
              Messages.getString("DynamicSQLRowMeta.CheckResult.SQLFieldNameMissing"),
              stepinfo); //$NON-NLS-1$
      remarks.add(cr);
    } else {
      ValueMetaInterface vfield = prev.searchValueMeta(sqlfieldname);
      if (vfield == null)
        cr =
            new CheckResult(
                CheckResult.TYPE_RESULT_ERROR,
                Messages.getString("DynamicSQLRowMeta.CheckResult.SQLFieldNotFound", sqlfieldname),
                stepinfo); //$NON-NLS-1$
      else
        cr =
            new CheckResult(
                CheckResult.TYPE_RESULT_OK,
                Messages.getString(
                    "DynamicSQLRowMeta.CheckResult.SQLFieldFound",
                    sqlfieldname,
                    vfield.getOrigin()),
                stepinfo);
      remarks.add(cr);
    }

    if (databaseMeta != null) {
      Database db = new Database(databaseMeta);
      databases = new Database[] {db}; // Keep track of this one for cancelQuery

      try {
        db.connect();
        if (sql != null && sql.length() != 0) {

          error_message = ""; // $NON-NLS-1$

          RowMetaInterface r = db.getQueryFields(sql, true);
          if (r != null) {
            cr =
                new CheckResult(
                    CheckResult.TYPE_RESULT_OK,
                    Messages.getString("DynamicSQLRowMeta.CheckResult.QueryOK"),
                    stepinfo); //$NON-NLS-1$
            remarks.add(cr);
          } else {
            error_message =
                Messages.getString("DynamicSQLRowMeta.CheckResult.InvalidDBQuery"); // $NON-NLS-1$
            cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, error_message, stepinfo);
            remarks.add(cr);
          }
        }
      } catch (KettleException e) {
        error_message =
            Messages.getString("DynamicSQLRowMeta.CheckResult.ErrorOccurred")
                + e.getMessage(); // $NON-NLS-1$
        cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, error_message, stepinfo);
        remarks.add(cr);
      } finally {
        db.disconnect();
      }
    } else {
      error_message =
          Messages.getString("DynamicSQLRowMeta.CheckResult.InvalidConnection"); // $NON-NLS-1$
      cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, error_message, stepinfo);
      remarks.add(cr);
    }
  }