@Override
  public String getFieldDefinition(
      ValueMetaInterface v,
      String tk,
      String pk,
      boolean use_autoinc,
      boolean add_fieldname,
      boolean add_cr) {
    String retval = "";

    String fieldname = v.getName();
    int length = v.getLength();
    int precision = v.getPrecision();

    if (add_fieldname) retval += fieldname + " ";

    int type = v.getType();
    switch (type) {
      case ValueMetaInterface.TYPE_DATE:
        retval += "DATETIME";
        break;
      case ValueMetaInterface.TYPE_BOOLEAN:
        retval += "CHAR(1)";
        break;
      case ValueMetaInterface.TYPE_NUMBER:
      case ValueMetaInterface.TYPE_INTEGER:
      case ValueMetaInterface.TYPE_BIGNUMBER:
        retval += "DECIMAL";
        if (length > 0) {
          retval += "(" + length;
          if (precision > 0) {
            retval += ", " + precision;
          }
          retval += ")";
        }
        break;
      case ValueMetaInterface.TYPE_STRING:
        if (length >= DatabaseMeta.CLOB_LENGTH) {
          retval += "CLOB";
        } else {
          retval += "VARCHAR";
          if (length > 0) {
            retval += "(" + length;
          } else {
            retval += "("; // Maybe use some default DB String length?
          }
          retval += ")";
        }
        break;
      default:
        retval += " UNKNOWN";
        break;
    }

    if (add_cr) retval += Const.CR;

    return retval;
  }
  protected JsonInput createBasicTestJsonInput(
      String jsonPath, ValueMetaInterface outputMeta, final String inCol, Object[]... inputRows) {
    JsonInputField jpath = new JsonInputField(outputMeta.getName());
    jpath.setPath(jsonPath);
    jpath.setType(outputMeta.getType());

    JsonInputMeta meta = createSimpleMeta(inCol, jpath);
    return createJsonInput(inCol, meta, inputRows);
  }
  private Date getIncrementalFieldValue() throws KettleException {
    Date result = null;
    boolean firstRow = true;
    Object[] row;
    RowMetaInterface inputRowMeta;

    while ((row = getRow()) != null) {
      if (firstRow) {
        firstRow = false;
        inputRowMeta = getInputRowMeta();

        if (inputRowMeta == null || inputRowMeta.size() <= 0) {
          if (log.isBasic()) {
            logBasic(BaseMessages.getString(PKG, "ZendeskInput.Error.NoIncomingRows"));
          }
          return null;
        }

        String filenameField = environmentSubstitute(meta.getTimestampFieldName());
        int fieldIndex = inputRowMeta.indexOfValue(filenameField);
        if (fieldIndex < 0) {
          throw new KettleStepException(
              BaseMessages.getString(
                  PKG, "ZendeskInputIncremental.Exception.StartDateFieldNotFound", filenameField));
        }
        ValueMetaInterface fieldValueMeta = inputRowMeta.getValueMeta(fieldIndex);
        if (!(fieldValueMeta instanceof ValueMetaDate)) {
          throw new KettleStepException(
              BaseMessages.getString(
                  PKG,
                  "ZendeskInput.Error.WrongFieldType",
                  ValueMetaFactory.getValueMetaName(fieldValueMeta.getType())));
        } else {
          result = fieldValueMeta.getDate(row[fieldIndex]);
        }
      } else {
        if (log.isDetailed()) {
          logDetailed(
              BaseMessages.getString(PKG, "ZendeskInput.Warning.IgnoringAdditionalInputRows"));
        }
      }
    }

    if (firstRow) {
      if (log.isBasic()) {
        logBasic(BaseMessages.getString(PKG, "ZendeskInput.Error.NoIncomingRows"));
      }
    }

    return result;
  }
  public static Object[] createObjectsForRow(RowMetaInterface rowMeta, Object[] rowData)
      throws KettleValueException {
    Object[] values = new Object[rowMeta.size()];
    for (int i = 0; i < rowMeta.size(); i++) {
      ValueMetaInterface valueMeta = rowMeta.getValueMeta(i);
      Object valueData = rowData[i];

      // Prevent a NullPointerException below
      if (valueData == null || valueMeta == null) {
        values[i] = null;
        continue;
      }

      int length = valueMeta.getLength();

      switch (valueMeta.getType()) {
        case ValueMetaInterface.TYPE_INTEGER:
          if (length < 3) {
            values[i] = new Byte(valueMeta.getInteger(valueData).byteValue());
          } else {
            if (length < 5) {
              values[i] = new Short(valueMeta.getInteger(valueData).shortValue());
            } else {
              values[i] = valueMeta.getInteger(valueData);
            }
          }
          break;
        case ValueMetaInterface.TYPE_NUMBER:
          values[i] = valueMeta.getNumber(valueData);
          break;
        case ValueMetaInterface.TYPE_DATE:
          values[i] = valueMeta.getDate(valueData);
          break;
        case ValueMetaInterface.TYPE_STRING:
          values[i] = valueMeta.getString(valueData);
          break;
        case ValueMetaInterface.TYPE_BINARY:
          values[i] = valueMeta.getBinary(valueData);
          break;
        case ValueMetaInterface.TYPE_BOOLEAN:
          values[i] = valueMeta.getBoolean(valueData);
          break;
        case ValueMetaInterface.TYPE_BIGNUMBER:
          values[i] = valueMeta.getNumber(valueData);
          break;
        default:
          break;
      }
    }
    return values;
  }
  public static ValueMetaInterface cloneValueMeta(ValueMetaInterface source, int targetType)
      throws KettlePluginException {
    ValueMetaInterface target = null;

    // If we're Cloneable and not changing types, call clone()
    if (source instanceof Cloneable && source.getType() == targetType) {
      target = source.clone();
    } else {
      target =
          createValueMeta(source.getName(), targetType, source.getLength(), source.getPrecision());
    }
    target.setConversionMask(source.getConversionMask());
    target.setDecimalSymbol(source.getDecimalSymbol());
    target.setGroupingSymbol(source.getGroupingSymbol());
    target.setStorageType(source.getStorageType());
    if (source.getStorageMetadata() != null) {
      target.setStorageMetadata(
          cloneValueMeta(source.getStorageMetadata(), source.getStorageMetadata().getType()));
    }
    target.setStringEncoding(source.getStringEncoding());
    target.setTrimType(source.getTrimType());
    target.setDateFormatLenient(source.isDateFormatLenient());
    target.setDateFormatLocale(source.getDateFormatLocale());
    target.setDateFormatTimeZone(source.getDateFormatTimeZone());
    target.setLenientStringToNumber(source.isLenientStringToNumber());
    target.setLargeTextField(source.isLargeTextField());
    target.setComments(source.getComments());
    target.setCaseInsensitive(source.isCaseInsensitive());
    target.setIndex(source.getIndex());

    target.setOrigin(source.getOrigin());

    target.setOriginalAutoIncrement(source.isOriginalAutoIncrement());
    target.setOriginalColumnType(source.getOriginalColumnType());
    target.setOriginalColumnTypeName(source.getOriginalColumnTypeName());
    target.setOriginalNullable(source.isOriginalNullable());
    target.setOriginalPrecision(source.getOriginalPrecision());
    target.setOriginalScale(source.getOriginalScale());
    target.setOriginalSigned(source.isOriginalSigned());

    return target;
  }
 public static ValueMetaInterface cloneValueMeta(ValueMetaInterface source)
     throws KettlePluginException {
   return cloneValueMeta(source, source.getType());
 }
  @Override
  public String getFieldDefinition(
      ValueMetaInterface v,
      String tk,
      String pk,
      boolean use_autoinc,
      boolean add_fieldname,
      boolean add_cr) {
    String retval = "";

    String fieldname = v.getName();
    int length = v.getLength();
    int precision = v.getPrecision();

    if (add_fieldname) {
      retval += fieldname + " ";
    }

    int type = v.getType();
    switch (type) {
      case ValueMetaInterface.TYPE_DATE:
        retval += "TIMESTAMP";
        break;
      case ValueMetaInterface.TYPE_BOOLEAN:
        retval += "CHAR(1)";
        break;
      case ValueMetaInterface.TYPE_NUMBER:
      case ValueMetaInterface.TYPE_INTEGER:
      case ValueMetaInterface.TYPE_BIGNUMBER:
        if (fieldname.equalsIgnoreCase(tk)
            || // Technical key
            fieldname.equalsIgnoreCase(pk) // Primary key
        ) {
          if (use_autoinc) {
            retval += "BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 0, INCREMENT BY 1)";
          } else {
            retval += "BIGINT NOT NULL PRIMARY KEY";
          }
        } else {
          // Integer values...
          if (precision == 0) {
            if (length > 9) {
              retval += "BIGINT";
            } else {
              if (length > 4) {
                retval += "INTEGER";
              } else {
                retval += "SMALLINT";
              }
            }
          } else {
            // Floating point values...
            if (length > 18) {
              retval += "DECIMAL(" + length;
              if (precision > 0) {
                retval += ", " + precision;
              }
              retval += ")";
            } else {
              retval += "FLOAT";
            }
          }
        }
        break;
      case ValueMetaInterface.TYPE_STRING:
        if (length >= DatabaseMeta.CLOB_LENGTH || length > 32700) {
          retval += "CLOB";
        } else {
          retval += "VARCHAR";
          if (length > 0) {
            retval += "(" + length;
          } else {
            retval += "("; // Maybe use some default DB String length?
          }
          retval += ")";
        }
        break;
      case ValueMetaInterface.TYPE_BINARY:
        retval += "BLOB";
        break;
      default:
        retval += "UNKNOWN";
        break;
    }

    if (add_cr) {
      retval += Const.CR;
    }

    return retval;
  }
  public void writeLine(RowMetaInterface mi, Object[] row) throws KettleException {
    if (first) {
      first = false;

      enclosure = meta.getEnclosure();

      // Setup up the fields we need to take for each of the rows
      // as this speeds up processing.
      fieldNumbers = new int[meta.getFieldStream().length];
      for (int i = 0; i < fieldNumbers.length; i++) {
        fieldNumbers[i] = mi.indexOfValue(meta.getFieldStream()[i]);
        if (fieldNumbers[i] < 0) {
          throw new KettleException(
              "Could not find field " + meta.getFieldStream()[i] + " in stream");
        }
      }

      sdfDate = new SimpleDateFormat("yyyy-MM-dd");
      sdfDateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

      outbuf = new StringBuilder();
    }
    outbuf.setLength(0);

    // Write the data to the output
    ValueMetaInterface v = null;
    int number = 0;
    for (int i = 0; i < fieldNumbers.length; i++) {
      if (i != 0) {
        outbuf.append(",");
      }
      v = mi.getValueMeta(i);
      number = fieldNumbers[i];
      if (row[number] == null) {
        // TODO (SB): special check for null in case of Strings.
        outbuf.append(enclosure);
        outbuf.append(enclosure);
      } else {
        switch (v.getType()) {
          case ValueMetaInterface.TYPE_STRING:
            String s = mi.getString(row, number);
            if (s.indexOf(enclosure) >= 0) {
              s = createEscapedString(s, enclosure);
            }
            outbuf.append(enclosure);
            outbuf.append(s);
            outbuf.append(enclosure);
            break;
          case ValueMetaInterface.TYPE_INTEGER:
            Long l = mi.getInteger(row, number);
            outbuf.append(enclosure);
            outbuf.append(l);
            outbuf.append(enclosure);
            break;
          case ValueMetaInterface.TYPE_NUMBER:
            Double d = mi.getNumber(row, number);
            outbuf.append(enclosure);
            outbuf.append(d);
            outbuf.append(enclosure);
            break;
          case ValueMetaInterface.TYPE_BIGNUMBER:
            BigDecimal bd = mi.getBigNumber(row, number);
            outbuf.append(enclosure);
            outbuf.append(bd);
            outbuf.append(enclosure);
            break;
          case ValueMetaInterface.TYPE_DATE:
            Date dt = mi.getDate(row, number);
            outbuf.append(enclosure);
            String mask = meta.getDateMask()[i];
            if (OraBulkLoaderMeta.DATE_MASK_DATETIME.equals(mask)) {
              outbuf.append(sdfDateTime.format(dt));
            } else {
              // Default is date format
              outbuf.append(sdfDate.format(dt));
            }
            outbuf.append(enclosure);
            break;
          case ValueMetaInterface.TYPE_BOOLEAN:
            Boolean b = mi.getBoolean(row, number);
            outbuf.append(enclosure);
            if (b.booleanValue()) {
              outbuf.append("Y");
            } else {
              outbuf.append("N");
            }
            outbuf.append(enclosure);
            break;
          case ValueMetaInterface.TYPE_BINARY:
            byte[] byt = mi.getBinary(row, number);
            outbuf.append("<startlob>");
            outbuf.append(byt);
            outbuf.append("<endlob>");
            break;
          default:
            throw new KettleException("Unsupported type");
        }
      }
    }
    outbuf.append(recTerm);
    try {
      output.append(outbuf);
    } catch (IOException e) {
      throw new KettleException("IO exception occured: " + e.getMessage(), e);
    }
  }
Example #9
0
  /**
   * Performs the lookup based on the meta-data and the input row.
   *
   * @param row The row to use as lookup data and the row to add the returned lookup fields to
   * @return the resulting row after the lookup values where added
   * @throws KettleException In case something goes wrong.
   */
  private synchronized Object[] lookupValues(RowMetaInterface inputRowMeta, Object[] row)
      throws KettleException {
    Object[] outputRow = RowDataUtil.resizeArray(row, data.outputRowMeta.size());

    Object[] lookupRow = new Object[data.lookupMeta.size()];
    int lookupIndex = 0;

    for (int i = 0; i < meta.getStreamKeyField1().length; i++) {
      if (data.keynrs[i] >= 0) {
        ValueMetaInterface input = inputRowMeta.getValueMeta(data.keynrs[i]);
        ValueMetaInterface value = data.lookupMeta.getValueMeta(lookupIndex);
        lookupRow[lookupIndex] = row[data.keynrs[i]];

        // Try to convert type if needed
        if (input.getType() != value.getType()) {
          lookupRow[lookupIndex] = value.convertData(input, lookupRow[lookupIndex]);
        }
        lookupIndex++;
      }
      if (data.keynrs2[i] >= 0) {
        ValueMetaInterface input = inputRowMeta.getValueMeta(data.keynrs2[i]);
        ValueMetaInterface value = data.lookupMeta.getValueMeta(lookupIndex);
        lookupRow[lookupIndex] = row[data.keynrs2[i]];

        // Try to convert type if needed
        if (input.getType() != value.getType()) {
          lookupRow[lookupIndex] = value.convertData(input, lookupRow[lookupIndex]);
        }
        lookupIndex++;
      }
    }

    Object[] add = null;
    boolean cache_now = false;
    boolean cacheHit = false;

    // First, check if we looked up before
    if (meta.isCached()) {
      add = getRowFromCache(data.lookupMeta, lookupRow);
      if (add != null) {
        cacheHit = true;
      }
    } else {
      add = null;
    }

    if (add == null) {
      if (!(meta.isCached() && meta.isLoadingAllDataInCache())
          || data.hasDBCondition) { // do not go to the
        // database when all rows
        // are in (exception LIKE
        // operator)
        if (log.isRowLevel()) {
          logRowlevel(
              BaseMessages.getString(PKG, "DatabaseLookup.Log.AddedValuesToLookupRow1")
                  + meta.getStreamKeyField1().length
                  + BaseMessages.getString(PKG, "DatabaseLookup.Log.AddedValuesToLookupRow2")
                  + data.lookupMeta.getString(lookupRow));
        }

        data.db.setValuesLookup(data.lookupMeta, lookupRow);
        add = data.db.getLookup(meta.isFailingOnMultipleResults());
        cache_now = true;
      }
    }

    if (add == null) { // nothing was found, unknown code: add default values
      if (meta.isEatingRowOnLookupFailure()) {
        return null;
      }
      if (getStepMeta().isDoingErrorHandling()) {
        putError(getInputRowMeta(), row, 1L, "No lookup found", null, "DBL001");

        // return false else we would still be processed.
        return null;
      }

      if (log.isRowLevel()) {
        logRowlevel(BaseMessages.getString(PKG, "DatabaseLookup.Log.NoResultsFoundAfterLookup"));
      }

      add = new Object[data.returnMeta.size()];
      for (int i = 0; i < meta.getReturnValueField().length; i++) {
        if (data.nullif[i] != null) {
          add[i] = data.nullif[i];
        } else {
          add[i] = null;
        }
      }
    } else {
      if (log.isRowLevel()) {
        logRowlevel(
            BaseMessages.getString(PKG, "DatabaseLookup.Log.FoundResultsAfterLookup") + add);
      }

      // Only verify the data types if the data comes from the DB, NOT when we have a cache hit
      // In that case, we already know the data type is OK.
      if (!cacheHit) {
        incrementLinesInput();

        int[] types = meta.getReturnValueDefaultType();

        // The assumption here is that the types are in the same order
        // as the returned lookup row, but since we make the lookup row
        // that should not be a problem.
        //
        for (int i = 0; i < types.length; i++) {
          ValueMetaInterface returned = data.db.getReturnRowMeta().getValueMeta(i);
          ValueMetaInterface expected = data.returnMeta.getValueMeta(i);

          if (returned != null && types[i] > 0 && types[i] != returned.getType()) {
            // Set the type to the default return type
            add[i] = expected.convertData(returned, add[i]);
          }
        }
      }
    }

    // Store in cache if we need to!
    // If we already loaded all data into the cache, storing more makes no sense.
    //
    if (meta.isCached() && cache_now && !meta.isLoadingAllDataInCache() && data.allEquals) {
      storeRowInCache(data.lookupMeta, lookupRow, add);
    }

    for (int i = 0; i < data.returnMeta.size(); i++) {
      outputRow[inputRowMeta.size() + i] = add[i];
    }

    return outputRow;
  }
  public static final List<Column> getColumns(RowMetaInterface row) {
    List<Column> list = new ArrayList<Column>();

    for (int i = 0; i < row.size(); i++) {
      ValueMetaInterface value = row.getValueMeta(i);

      Column column = new Column();
      column.setName(value.getName());

      int length = value.getLength();

      switch (value.getType()) {
        case ValueMetaInterface.TYPE_INTEGER:
          if (length < 3) {
            column.setType(DataType.BYTE);
            length = DataType.BYTE.getFixedSize();
          } else {
            if (length < 5) {
              column.setType(DataType.INT);
              length = DataType.INT.getFixedSize();
            } else {
              column.setType(DataType.LONG);
              length = DataType.LONG.getFixedSize();
            }
          }
          break;
        case ValueMetaInterface.TYPE_NUMBER:
          column.setType(DataType.DOUBLE);
          length = DataType.DOUBLE.getFixedSize();
          break;
        case ValueMetaInterface.TYPE_DATE:
          column.setType(DataType.SHORT_DATE_TIME);
          length = DataType.SHORT_DATE_TIME.getFixedSize();
          break;
        case ValueMetaInterface.TYPE_STRING:
          if (length < 255) {
            column.setType(DataType.TEXT);
            length *= DataType.TEXT.getUnitSize();
          } else {
            column.setType(DataType.MEMO);
            length *= DataType.MEMO.getUnitSize();
          }
          break;
        case ValueMetaInterface.TYPE_BINARY:
          column.setType(DataType.BINARY);
          break;
        case ValueMetaInterface.TYPE_BOOLEAN:
          column.setType(DataType.BOOLEAN);
          length = DataType.BOOLEAN.getFixedSize();
          break;
        case ValueMetaInterface.TYPE_BIGNUMBER:
          column.setType(DataType.NUMERIC);
          length = DataType.NUMERIC.getFixedSize();
          break;
        default:
          break;
      }

      if (length >= 0) {
        column.setLength((short) length);
      }
      if (value.getPrecision() >= 1 && value.getPrecision() <= 28) {
        column.setPrecision((byte) value.getPrecision());
      }

      list.add(column);
    }

    return list;
  }
  private void populateTableWithIncomingFields() {
    if (m_incomingFieldsProducer != null) {
      RowMetaInterface incomingRowMeta = m_incomingFieldsProducer.getIncomingFields();

      Table table = m_fieldsView.table;
      if (incomingRowMeta != null) {
        Set<String> existingRowAliases = new HashSet<String>();
        for (int i = 0; i < table.getItemCount(); i++) {
          TableItem tableItem = table.getItem(i);
          String alias = tableItem.getText(1);
          if (!Const.isEmpty(alias)) {
            existingRowAliases.add(alias);
          }
        }

        int choice = 0;
        if (existingRowAliases.size() > 0) {
          // Ask what we should do with existing mapping data
          MessageDialog md =
              new MessageDialog(
                  m_shell,
                  Messages.getString("MappingDialog.GetFieldsChoice.Title"),
                  null,
                  Messages.getString(
                      "MappingDialog.GetFieldsChoice.Message",
                      "" + existingRowAliases.size(),
                      "" + incomingRowMeta.size()),
                  MessageDialog.WARNING,
                  new String[] {
                    Messages.getString("MappingDialog.AddNew"),
                    Messages.getString("MappingOutputDialog.Add"),
                    Messages.getString("MappingOutputDialog.ClearAndAdd"),
                    Messages.getString("MappingOutputDialog.Cancel"),
                  },
                  0);
          MessageDialog.setDefaultImage(GUIResource.getInstance().getImageSpoon());
          int idx = md.open();
          choice = idx & 0xFF;
        }

        if (choice == 3 || choice == 255 /* 255 = escape pressed */) {
          return; // Cancel
        }

        if (choice == 2) {
          m_fieldsView.clearAll();
        }

        for (int i = 0; i < incomingRowMeta.size(); i++) {
          ValueMetaInterface vm = incomingRowMeta.getValueMeta(i);
          boolean addIt = true;

          if (choice == 0) {
            // only add if its not already in the table
            if (existingRowAliases.contains(vm.getName())) {
              addIt = false;
            }
          }

          if (addIt) {
            TableItem item = new TableItem(m_fieldsView.table, SWT.NONE);
            item.setText(1, vm.getName());
            item.setText(2, "N");

            if (m_familyCI.getComboValues()[0].length() > 0) {
              // use existing first column family name as the default
              item.setText(3, m_familyCI.getComboValues()[0]);
            } else {
              // default
              item.setText(3, DEFAULT_FAMILY);
            }

            item.setText(4, vm.getName());
            item.setText(5, vm.getTypeDesc());
            if (vm.getType() == ValueMetaInterface.TYPE_INTEGER) {
              item.setText(5, "Long");
            }
            if (vm.getType() == ValueMetaInterface.TYPE_NUMBER) {
              item.setText(5, "Double");
            }
            if (vm.getStorageType() == ValueMetaInterface.STORAGE_TYPE_INDEXED) {
              Object[] indexValus = vm.getIndex();
              String indexValsS = HBaseValueMeta.objectIndexValuesToString(indexValus);
              item.setText(6, indexValsS);
            }
          }
        }

        m_fieldsView.removeEmptyRows();
        m_fieldsView.setRowNums();
        m_fieldsView.optWidth(true);
      }
    }
  }
Example #12
0
  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$
    boolean first = true;
    boolean error_found = false;

    if (prev == null) {
      error_message +=
          BaseMessages.getString(PKG, "StringCutMeta.CheckResult.NoInputReceived")
              + Const.CR; // $NON-NLS-1$
      cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, error_message, stepinfo);
      remarks.add(cr);
    } else {

      for (int i = 0; i < fieldInStream.length; i++) {
        String field = fieldInStream[i];

        ValueMetaInterface v = prev.searchValueMeta(field);
        if (v == null) {
          if (first) {
            first = false;
            error_message +=
                BaseMessages.getString(PKG, "StringCutMeta.CheckResult.MissingInStreamFields")
                    + Const.CR; // $NON-NLS-1$
          }
          error_found = true;
          error_message += "\t\t" + field + Const.CR; // $NON-NLS-1$
        }
      }
      if (error_found) {
        cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, error_message, stepinfo);
      } else {
        cr =
            new CheckResult(
                CheckResult.TYPE_RESULT_OK,
                BaseMessages.getString(PKG, "StringCutMeta.CheckResult.FoundInStreamFields"),
                stepinfo); //$NON-NLS-1$
      }
      remarks.add(cr);

      // Check whether all are strings
      first = true;
      error_found = false;
      for (int i = 0; i < fieldInStream.length; i++) {
        String field = fieldInStream[i];

        ValueMetaInterface v = prev.searchValueMeta(field);
        if (v != null) {
          if (v.getType() != ValueMeta.TYPE_STRING) {
            if (first) {
              first = false;
              error_message +=
                  BaseMessages.getString(
                          PKG, "StringCutMeta.CheckResult.OperationOnNonStringFields")
                      + Const.CR; // $NON-NLS-1$
            }
            error_found = true;
            error_message += "\t\t" + field + Const.CR; // $NON-NLS-1$
          }
        }
      }
      if (error_found) {
        cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, error_message, stepinfo);
      } else {
        cr =
            new CheckResult(
                CheckResult.TYPE_RESULT_OK,
                BaseMessages.getString(
                    PKG, "StringCutMeta.CheckResult.AllOperationsOnStringFields"),
                stepinfo); //$NON-NLS-1$
      }
      remarks.add(cr);

      if (fieldInStream.length > 0) {
        for (int idx = 0; idx < fieldInStream.length; idx++) {
          if (Const.isEmpty(fieldInStream[idx])) {
            cr =
                new CheckResult(
                    CheckResult.TYPE_RESULT_ERROR,
                    BaseMessages.getString(
                        PKG,
                        "StringCutMeta.CheckResult.InStreamFieldMissing",
                        new Integer(idx + 1).toString()),
                    stepinfo); //$NON-NLS-1$
            remarks.add(cr);
          }
        }
      }
    }
  }
  private Object[] lookupValues(RowMetaInterface rowMeta, Object[] row) throws KettleException {
    // See if we need to stop.
    if (isStopped()) return null;

    if (data.lookupColumnIndex == null) {
      String names[] = data.lookupMeta.getFieldNames();
      data.lookupColumnIndex = new int[names.length];

      for (int i = 0; i < names.length; i++) {
        data.lookupColumnIndex[i] = rowMeta.indexOfValue(names[i]);
        if (data.lookupColumnIndex[i] < 0) {
          // we should not get here
          throw new KettleStepException("The lookup column '" + names[i] + "' could not be found");
        }
      }
    }

    // Copy value references to lookup table.
    //
    Object[] lu = new Object[data.keynrs.length];
    for (int i = 0; i < data.keynrs.length; i++) {
      // If the input is binary storage data, we convert it to normal storage.
      //
      if (data.convertKeysToNative[i]) {
        lu[i] =
            data.lookupMeta
                .getValueMeta(i)
                .convertBinaryStringToNativeType((byte[]) row[data.keynrs[i]]);
      } else {
        lu[i] = row[data.keynrs[i]];
      }
    }

    // Handle conflicting types (Number-Integer-String conversion to lookup type in hashtable)
    if (data.keyTypes != null) {
      for (int i = 0; i < data.lookupMeta.size(); i++) {
        ValueMetaInterface inputValue = data.lookupMeta.getValueMeta(i);
        ValueMetaInterface lookupValue = data.keyTypes.getValueMeta(i);
        if (inputValue.getType() != lookupValue.getType()) {
          try {
            // Change the input value to match the lookup value
            //
            lu[i] = lookupValue.convertDataCompatible(inputValue, lu[i]);
          } catch (KettleValueException e) {
            throw new KettleStepException("Error converting data while looking up value", e);
          }
        }
      }
    }

    Object[] add = null;

    if (data.hasLookupRows) {
      try {
        if (meta.getKeystream().length > 0) {
          add = getFromCache(data.keyTypes, lu);
        } else {
          // Just take the first element in the hashtable...
          throw new KettleStepException(
              BaseMessages.getString(PKG, "StreamLookup.Log.GotRowWithoutKeys")); // $NON-NLS-1$
        }
      } catch (Exception e) {
        throw new KettleStepException(e);
      }
    }

    if (add == null) // nothing was found, unknown code: add the specified default value...
    {
      add = data.nullIf;
    }

    return RowDataUtil.addRowData(row, rowMeta.size(), add);
  }
Example #14
0
  /**
   * Get the contents of the control file as specified in the meta object
   *
   * @param meta the meta object to model the control file after
   * @return a string containing the control file contents
   */
  public String getControlFileContents(OraBulkLoaderMeta meta, RowMetaInterface rm, Object[] r)
      throws KettleException {
    DatabaseMeta dm = meta.getDatabaseMeta();
    String inputName = "'" + environmentSubstitute(meta.getDataFile()) + "'";

    String loadAction = meta.getLoadAction();

    StringBuilder contents = new StringBuilder(500);
    contents.append("OPTIONS(").append(Const.CR);
    contents.append("  ERRORS=\'").append(meta.getMaxErrors()).append("\'").append(Const.CR);

    if (meta.getCommitSizeAsInt(this) != 0
        && !(meta.isDirectPath() && getStepMeta().getCopies() > 1)) {
      // For the second part of the above expressions: ROWS is not supported
      // in parallel mode (by sqlldr).
      contents.append("  , ROWS=\'").append(meta.getCommitSize()).append("\'").append(Const.CR);
    }

    if (meta.getBindSizeAsInt(this) != 0) {
      contents.append("  , BINDSIZE=\'").append(meta.getBindSize()).append("\'").append(Const.CR);
    }

    if (meta.getReadSizeAsInt(this) != 0) {
      contents.append("  , READSIZE=\'").append(meta.getReadSize()).append("\'").append(Const.CR);
    }

    contents.append(")").append(Const.CR);

    contents.append("LOAD DATA").append(Const.CR);
    if (!Utils.isEmpty(meta.getCharacterSetName())) {
      contents.append("CHARACTERSET ").append(meta.getCharacterSetName()).append(Const.CR);
    }
    if (!OraBulkLoaderMeta.METHOD_AUTO_CONCURRENT.equals(meta.getLoadMethod())
        || !Utils.isEmpty(meta.getAltRecordTerm())) {
      String infile = inputName;

      if (OraBulkLoaderMeta.METHOD_AUTO_CONCURRENT.equals(meta.getLoadMethod())) {
        infile = "''";
      }

      // For concurrent input, data command line argument must be specified
      contents.append("INFILE ").append(infile);
      if (!Utils.isEmpty(meta.getAltRecordTerm())) {
        contents
            .append(" \"STR x'")
            .append(encodeRecordTerminator(meta.getAltRecordTerm(), meta.getEncoding()))
            .append("'\"");
      }
      contents.append(Const.CR);
    }
    contents
        .append("INTO TABLE ")
        .append(
            dm.getQuotedSchemaTableCombination(
                environmentSubstitute(meta.getSchemaName()),
                environmentSubstitute(meta.getTableName())))
        .append(Const.CR)
        .append(loadAction)
        .append(Const.CR)
        .append("FIELDS TERMINATED BY ',' ENCLOSED BY '\"'")
        .append(Const.CR)
        .append("(");

    String[] streamFields = meta.getFieldStream();
    String[] tableFields = meta.getFieldTable();
    String[] dateMask = meta.getDateMask();

    if (streamFields == null || streamFields.length == 0) {
      throw new KettleException("No fields defined to load to database");
    }

    for (int i = 0; i < streamFields.length; i++) {
      if (i != 0) {
        contents.append(", ").append(Const.CR);
      }
      contents.append(dm.quoteField(tableFields[i]));

      int pos = rm.indexOfValue(streamFields[i]);
      if (pos < 0) {
        throw new KettleException("Could not find field " + streamFields[i] + " in stream");
      }
      ValueMetaInterface v = rm.getValueMeta(pos);
      switch (v.getType()) {
        case ValueMetaInterface.TYPE_STRING:
          if (v.getLength() > 255) {
            contents.append(" CHAR(").append(v.getLength()).append(")");
          } else {
            contents.append(" CHAR");
          }
          break;
        case ValueMetaInterface.TYPE_INTEGER:
        case ValueMetaInterface.TYPE_NUMBER:
        case ValueMetaInterface.TYPE_BIGNUMBER:
          break;
        case ValueMetaInterface.TYPE_DATE:
          if (OraBulkLoaderMeta.DATE_MASK_DATE.equals(dateMask[i])) {
            contents.append(" DATE 'yyyy-mm-dd'");
          } else if (OraBulkLoaderMeta.DATE_MASK_DATETIME.equals(dateMask[i])) {
            contents.append(" TIMESTAMP 'yyyy-mm-dd hh24:mi:ss.ff'");
          } else {
            // If not specified the default is date.
            contents.append(" DATE 'yyyy-mm-dd'");
          }
          break;
        case ValueMetaInterface.TYPE_BINARY:
          contents.append(" ENCLOSED BY '<startlob>' AND '<endlob>'");
          break;
        case ValueMetaInterface.TYPE_TIMESTAMP:
          contents.append(" TIMESTAMP 'yyyy-mm-dd hh24:mi:ss.ff'");
          break;
        default:
          break;
      }
    }
    contents.append(")");

    return contents.toString();
  }
Example #15
0
  @Override
  public void getFields(
      RowMetaInterface rowMeta,
      String origin,
      RowMetaInterface[] info,
      StepMeta nextStep,
      VariableSpace space,
      Repository repository,
      IMetaStore metaStore) {
    // re-assemble a new row of metadata
    //
    RowMetaInterface fields = new RowMeta();

    if (!passAllRows) {
      // Add the grouping fields in the correct order...
      //
      for (int i = 0; i < groupField.length; i++) {
        ValueMetaInterface valueMeta = rowMeta.searchValueMeta(groupField[i]);
        if (valueMeta != null) {
          fields.addValueMeta(valueMeta);
        }
      }
    } else {
      // Add all the original fields from the incoming row meta
      //
      fields.addRowMeta(rowMeta);
    }

    // Re-add aggregates
    //
    for (int i = 0; i < subjectField.length; i++) {
      ValueMetaInterface subj = rowMeta.searchValueMeta(subjectField[i]);
      if (subj != null || aggregateType[i] == TYPE_GROUP_COUNT_ANY) {
        String valueName = aggregateField[i];
        int valueType = ValueMetaInterface.TYPE_NONE;
        int length = -1;
        int precision = -1;

        switch (aggregateType[i]) {
          case TYPE_GROUP_SUM:
          case TYPE_GROUP_AVERAGE:
          case TYPE_GROUP_CUMULATIVE_SUM:
          case TYPE_GROUP_CUMULATIVE_AVERAGE:
          case TYPE_GROUP_FIRST:
          case TYPE_GROUP_LAST:
          case TYPE_GROUP_FIRST_INCL_NULL:
          case TYPE_GROUP_LAST_INCL_NULL:
          case TYPE_GROUP_MIN:
          case TYPE_GROUP_MAX:
            valueType = subj.getType();
            break;
          case TYPE_GROUP_COUNT_DISTINCT:
          case TYPE_GROUP_COUNT_ANY:
          case TYPE_GROUP_COUNT_ALL:
            valueType = ValueMetaInterface.TYPE_INTEGER;
            break;
          case TYPE_GROUP_CONCAT_COMMA:
            valueType = ValueMetaInterface.TYPE_STRING;
            break;
          case TYPE_GROUP_STANDARD_DEVIATION:
          case TYPE_GROUP_MEDIAN:
          case TYPE_GROUP_PERCENTILE:
            valueType = ValueMetaInterface.TYPE_NUMBER;
            break;
          case TYPE_GROUP_CONCAT_STRING:
            valueType = ValueMetaInterface.TYPE_STRING;
            break;
          default:
            break;
        }

        // Change type from integer to number in case off averages for cumulative average
        //
        if (aggregateType[i] == TYPE_GROUP_CUMULATIVE_AVERAGE
            && valueType == ValueMetaInterface.TYPE_INTEGER) {
          valueType = ValueMetaInterface.TYPE_NUMBER;
          precision = -1;
          length = -1;
        } else if (aggregateType[i] == TYPE_GROUP_COUNT_ALL
            || aggregateType[i] == TYPE_GROUP_COUNT_DISTINCT
            || aggregateType[i] == TYPE_GROUP_COUNT_ANY) {
          length = ValueMetaInterface.DEFAULT_INTEGER_LENGTH;
          precision = 0;
        } else if (aggregateType[i] == TYPE_GROUP_SUM
            && valueType != ValueMetaInterface.TYPE_INTEGER
            && valueType != ValueMetaInterface.TYPE_NUMBER
            && valueType != ValueMetaInterface.TYPE_BIGNUMBER) {
          // If it ain't numeric, we change it to Number
          //
          valueType = ValueMetaInterface.TYPE_NUMBER;
          precision = -1;
          length = -1;
        }

        if (valueType != ValueMetaInterface.TYPE_NONE) {
          ValueMetaInterface v = new ValueMeta(valueName, valueType);
          v.setOrigin(origin);
          v.setLength(length, precision);
          fields.addValueMeta(v);
        }
      }
    }

    if (passAllRows) {
      // If we pass all rows, we can add a line nr in the group...
      if (addingLineNrInGroup && !Utils.isEmpty(lineNrInGroupField)) {
        ValueMetaInterface lineNr = new ValueMetaInteger(lineNrInGroupField);
        lineNr.setLength(ValueMetaInterface.DEFAULT_INTEGER_LENGTH, 0);
        lineNr.setOrigin(origin);
        fields.addValueMeta(lineNr);
      }
    }

    // Now that we have all the fields we want, we should clear the original row and replace the
    // values...
    //
    rowMeta.clear();
    rowMeta.addRowMeta(fields);
  }
  @Override
  public String getFieldDefinition(
      ValueMetaInterface v,
      String tk,
      String pk,
      boolean use_autoinc,
      boolean add_fieldname,
      boolean add_cr) {
    String retval = "";

    String fieldname = v.getName();
    int length = v.getLength();
    int precision = v.getPrecision();

    if (add_fieldname) {
      retval += fieldname + " ";
    }

    int type = v.getType();
    switch (type) {
      case ValueMetaInterface.TYPE_DATE:
        retval += "DATETIME";
        break;
      case ValueMetaInterface.TYPE_BOOLEAN:
        if (supportsBooleanDataType()) {
          retval += "BIT";
        } else {
          retval += "CHAR(1)";
        }
        break;
      case ValueMetaInterface.TYPE_NUMBER:
      case ValueMetaInterface.TYPE_INTEGER:
      case ValueMetaInterface.TYPE_BIGNUMBER:
        if (fieldname.equalsIgnoreCase(tk)
            || // Technical key
            fieldname.equalsIgnoreCase(pk) // Primary key
        ) {
          if (use_autoinc) {
            retval += "BIGINT PRIMARY KEY IDENTITY(0,1)";
          } else {
            retval += "BIGINT PRIMARY KEY";
          }
        } else {
          if (precision == 0) {
            if (length > 18) {
              retval += "DECIMAL(" + length + ",0)";
            } else {
              if (length > 9) {
                retval += "BIGINT";
              } else {
                retval += "INT";
              }
            }
          } else {
            if (precision > 0) {
              if (length > 0) {
                retval += "DECIMAL(" + length + "," + precision + ")";
              }
            } else {
              retval += "FLOAT(53)";
            }
          }
        }
        break;
      case ValueMetaInterface.TYPE_STRING:
        if (length < getMaxVARCHARLength()) {
          // Maybe use some default DB String length in case length<=0
          if (length > 0) {
            retval += "VARCHAR(" + length + ")";
          } else {
            retval += "VARCHAR(100)";
          }
        } else {
          retval += "TEXT"; // Up to 2bilion characters.
        }
        break;
      default:
        retval += " UNKNOWN";
        break;
    }

    if (add_cr) {
      retval += Const.CR;
    }

    return retval;
  }
Example #17
0
  public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
    meta = (DatabaseLookupMeta) smi;
    data = (DatabaseLookupData) sdi;

    boolean sendToErrorRow = false;
    String errorMessage = null;

    Object[] r = getRow(); // Get row from input rowset & set row busy!
    if (r == null) { // no more input to be expected...
      setOutputDone();
      return false;
    }

    if (first) {
      first = false;

      // create the output metadata
      data.outputRowMeta = getInputRowMeta().clone();
      meta.getFields(data.outputRowMeta, getStepname(), null, null, this, repository, metaStore);

      if (meta.isCached()) {
        if (meta.getCacheSize() > 0) {
          data.look = new Hashtable<RowMetaAndData, TimedRow>((int) (meta.getCacheSize() * 1.5));
        } else {
          data.look = new Hashtable<RowMetaAndData, TimedRow>();
        }
      }

      data.db.setLookup(
          environmentSubstitute(meta.getSchemaName()),
          environmentSubstitute(meta.getTablename()),
          meta.getTableKeyField(),
          meta.getKeyCondition(),
          meta.getReturnValueField(),
          meta.getReturnValueNewName(),
          meta.getOrderByClause(),
          meta.isFailingOnMultipleResults());

      // lookup the values!
      if (log.isDetailed()) {
        logDetailed(
            BaseMessages.getString(PKG, "DatabaseLookup.Log.CheckingRow")
                + getInputRowMeta().getString(r));
      }

      data.keynrs = new int[meta.getStreamKeyField1().length];
      data.keynrs2 = new int[meta.getStreamKeyField1().length];

      for (int i = 0; i < meta.getStreamKeyField1().length; i++) {
        data.keynrs[i] = getInputRowMeta().indexOfValue(meta.getStreamKeyField1()[i]);
        if (data.keynrs[i] < 0
            && // couldn't find field!
            !"IS NULL".equalsIgnoreCase(meta.getKeyCondition()[i])
            && // No field needed!
            !"IS NOT NULL".equalsIgnoreCase(meta.getKeyCondition()[i]) // No field needed!
        ) {
          throw new KettleStepException(
              BaseMessages.getString(PKG, "DatabaseLookup.ERROR0001.FieldRequired1.Exception")
                  + meta.getStreamKeyField1()[i]
                  + BaseMessages.getString(
                      PKG, "DatabaseLookup.ERROR0001.FieldRequired2.Exception"));
        }
        data.keynrs2[i] = getInputRowMeta().indexOfValue(meta.getStreamKeyField2()[i]);
        if (data.keynrs2[i] < 0
            && // couldn't find field!
            "BETWEEN".equalsIgnoreCase(meta.getKeyCondition()[i]) // 2 fields needed!
        ) {
          throw new KettleStepException(
              BaseMessages.getString(PKG, "DatabaseLookup.ERROR0001.FieldRequired3.Exception")
                  + meta.getStreamKeyField2()[i]
                  + BaseMessages.getString(
                      PKG, "DatabaseLookup.ERROR0001.FieldRequired4.Exception"));
        }
        if (log.isDebug()) {
          logDebug(
              BaseMessages.getString(PKG, "DatabaseLookup.Log.FieldHasIndex1")
                  + meta.getStreamKeyField1()[i]
                  + BaseMessages.getString(PKG, "DatabaseLookup.Log.FieldHasIndex2")
                  + data.keynrs[i]);
        }
      }

      data.nullif = new Object[meta.getReturnValueField().length];

      for (int i = 0; i < meta.getReturnValueField().length; i++) {
        ValueMetaInterface stringMeta = new ValueMeta("string", ValueMetaInterface.TYPE_STRING);
        ValueMetaInterface returnMeta =
            data.outputRowMeta.getValueMeta(i + getInputRowMeta().size());

        if (!Const.isEmpty(meta.getReturnValueDefault()[i])) {
          data.nullif[i] = returnMeta.convertData(stringMeta, meta.getReturnValueDefault()[i]);
        } else {
          data.nullif[i] = null;
        }
      }

      // Determine the types...
      data.keytypes = new int[meta.getTableKeyField().length];
      String schemaTable =
          meta.getDatabaseMeta()
              .getQuotedSchemaTableCombination(
                  environmentSubstitute(meta.getSchemaName()),
                  environmentSubstitute(meta.getTablename()));
      RowMetaInterface fields = data.db.getTableFields(schemaTable);
      if (fields != null) {
        // Fill in the types...
        for (int i = 0; i < meta.getTableKeyField().length; i++) {
          ValueMetaInterface key = fields.searchValueMeta(meta.getTableKeyField()[i]);
          if (key != null) {
            data.keytypes[i] = key.getType();
          } else {
            throw new KettleStepException(
                BaseMessages.getString(PKG, "DatabaseLookup.ERROR0001.FieldRequired5.Exception")
                    + meta.getTableKeyField()[i]
                    + BaseMessages.getString(
                        PKG, "DatabaseLookup.ERROR0001.FieldRequired6.Exception"));
          }
        }
      } else {
        throw new KettleStepException(
            BaseMessages.getString(PKG, "DatabaseLookup.ERROR0002.UnableToDetermineFieldsOfTable")
                + schemaTable
                + "]");
      }

      // Count the number of values in the lookup as well as the metadata to send along with it.
      //
      data.lookupMeta = new RowMeta();

      for (int i = 0; i < meta.getStreamKeyField1().length; i++) {
        if (data.keynrs[i] >= 0) {
          ValueMetaInterface inputValueMeta = getInputRowMeta().getValueMeta(data.keynrs[i]);

          // Try to convert type if needed in a clone, we don't want to
          // change the type in the original row
          //
          ValueMetaInterface value =
              ValueMetaFactory.cloneValueMeta(inputValueMeta, data.keytypes[i]);

          data.lookupMeta.addValueMeta(value);
        }
        if (data.keynrs2[i] >= 0) {
          ValueMetaInterface inputValueMeta = getInputRowMeta().getValueMeta(data.keynrs2[i]);

          // Try to convert type if needed in a clone, we don't want to
          // change the type in the original row
          //
          ValueMetaInterface value =
              ValueMetaFactory.cloneValueMeta(inputValueMeta, data.keytypes[i]);

          data.lookupMeta.addValueMeta(value);
        }
      }

      // We also want to know the metadata of the return values beforehand (null handling)
      data.returnMeta = new RowMeta();

      for (int i = 0; i < meta.getReturnValueField().length; i++) {
        ValueMetaInterface v =
            data.outputRowMeta.getValueMeta(getInputRowMeta().size() + i).clone();
        data.returnMeta.addValueMeta(v);
      }

      // If the user selected to load all data into the cache at startup, that's what we do now...
      //
      if (meta.isCached() && meta.isLoadingAllDataInCache()) {
        loadAllTableDataIntoTheCache();
      }
    }

    if (log.isRowLevel()) {
      logRowlevel(
          BaseMessages.getString(PKG, "DatabaseLookup.Log.GotRowFromPreviousStep")
              + getInputRowMeta().getString(r));
    }

    try {
      // add new lookup values to the row
      Object[] outputRow = lookupValues(getInputRowMeta(), r);

      if (outputRow != null) {
        // copy row to output rowset(s);
        putRow(data.outputRowMeta, outputRow);

        if (log.isRowLevel()) {
          logRowlevel(
              BaseMessages.getString(PKG, "DatabaseLookup.Log.WroteRowToNextStep")
                  + getInputRowMeta().getString(r));
        }
        if (checkFeedback(getLinesRead())) {
          logBasic("linenr " + getLinesRead());
        }
      }
    } catch (KettleException e) {
      if (getStepMeta().isDoingErrorHandling()) {
        sendToErrorRow = true;
        errorMessage = e.toString();
      } else {
        logError(
            BaseMessages.getString(PKG, "DatabaseLookup.ERROR003.UnexpectedErrorDuringProcessing")
                + e.getMessage());
        setErrors(1);
        stopAll();
        setOutputDone(); // signal end to receiver(s)
        return false;
      }
      if (sendToErrorRow) {
        // Simply add this row to the error row
        putError(getInputRowMeta(), r, 1, errorMessage, null, "DBLOOKUPD001");
      }
    }

    return true;
  }
  public void getFields(
      RowMetaInterface row,
      String origin,
      RowMetaInterface[] info,
      StepMeta nextStep,
      VariableSpace space)
      throws KettleStepException {
    // Row should normally be empty when we get here.
    // That is because there is no previous step to this mapping input step from the viewpoint of
    // this single sub-transformation.
    // From the viewpoint of the transformation that executes the mapping, it's important to know
    // what comes out at the exit points.
    // For that reason we need to re-order etc, based on the input specification...
    //
    if (inputRowMeta != null && !inputRowMeta.isEmpty()) {
      // this gets set only in the parent transformation...
      // It includes all the renames that needed to be done
      //
      if (selectingAndSortingUnspecifiedFields) {

        // First rename any fields...
        if (valueRenames != null) {
          for (MappingValueRename valueRename : valueRenames) {
            ValueMetaInterface valueMeta =
                inputRowMeta.searchValueMeta(valueRename.getSourceValueName());
            if (valueMeta == null) {
              throw new KettleStepException(
                  BaseMessages.getString(
                      PKG,
                      "MappingInput.Exception.UnableToFindMappedValue",
                      valueRename.getSourceValueName()));
            }
            valueMeta.setName(valueRename.getTargetValueName());
          }
        }

        // Select the specified fields from the input, re-order everything and put the other fields
        // at the back, sorted...
        //
        RowMetaInterface newRow = new RowMeta();

        for (int i = 0; i < fieldName.length; i++) {
          int index = inputRowMeta.indexOfValue(fieldName[i]);
          if (index < 0) {
            throw new KettleStepException(
                BaseMessages.getString(
                    PKG, "MappingInputMeta.Exception.UnknownField", fieldName[i]));
          }

          newRow.addValueMeta(inputRowMeta.getValueMeta(index));
        }

        // Now get the unspecified fields.
        // Sort the fields
        // Add them after the specified fields...
        //
        List<String> extra = new ArrayList<String>();
        for (int i = 0; i < inputRowMeta.size(); i++) {
          String fieldName = inputRowMeta.getValueMeta(i).getName();
          if (newRow.indexOfValue(fieldName) < 0) {
            extra.add(fieldName);
          }
        }
        Collections.sort(extra);
        for (String fieldName : extra) {
          ValueMetaInterface extraValue = inputRowMeta.searchValueMeta(fieldName);
          newRow.addValueMeta(extraValue);
        }

        // now merge the new row...
        // This is basically the input row meta data with the fields re-ordered.
        //
        row.mergeRowMeta(newRow);
      } else {
        row.mergeRowMeta(inputRowMeta);

        // Validate the existence of all the specified fields...
        //
        if (!row.isEmpty()) {
          for (int i = 0; i < fieldName.length; i++) {
            if (row.indexOfValue(fieldName[i]) < 0) {
              throw new KettleStepException(
                  BaseMessages.getString(
                      PKG, "MappingInputMeta.Exception.UnknownField", fieldName[i]));
            }
          }
        }
      }
    } else {
      // We'll have to work with the statically provided information
      for (int i = 0; i < fieldName.length; i++) {
        if (!Const.isEmpty(fieldName[i])) {
          ValueMetaInterface v = new ValueMeta(fieldName[i], fieldType[i]);
          if (v.getType() == ValueMetaInterface.TYPE_NONE)
            v.setType(ValueMetaInterface.TYPE_STRING);
          v.setLength(fieldLength[i]);
          v.setPrecision(fieldPrecision[i]);
          v.setOrigin(origin);
          row.addValueMeta(v);
        }
      }
    }
  }
  public static final RowMetaAndData buildRow(
      RowGeneratorMeta meta, List<CheckResultInterface> remarks, String origin) {
    RowMetaInterface rowMeta = new RowMeta();
    Object[] rowData = RowDataUtil.allocateRowData(meta.getFieldName().length);

    for (int i = 0; i < meta.getFieldName().length; i++) {
      int valtype = ValueMeta.getType(meta.getFieldType()[i]);
      if (meta.getFieldName()[i] != null) {
        ValueMetaInterface valueMeta =
            new ValueMeta(meta.getFieldName()[i], valtype); // build a value!
        valueMeta.setLength(meta.getFieldLength()[i]);
        valueMeta.setPrecision(meta.getFieldPrecision()[i]);
        valueMeta.setConversionMask(meta.getFieldFormat()[i]);
        valueMeta.setGroupingSymbol(meta.getGroup()[i]);
        valueMeta.setDecimalSymbol(meta.getDecimal()[i]);
        valueMeta.setOrigin(origin);

        ValueMetaInterface stringMeta = valueMeta.clone();
        stringMeta.setType(ValueMetaInterface.TYPE_STRING);

        String stringValue = meta.getValue()[i];

        // If the value is empty: consider it to be NULL.
        if (Const.isEmpty(stringValue)) {
          rowData[i] = null;

          if (valueMeta.getType() == ValueMetaInterface.TYPE_NONE) {
            String message =
                BaseMessages.getString(
                    PKG,
                    "RowGenerator.CheckResult.SpecifyTypeError",
                    valueMeta.getName(),
                    stringValue);
            remarks.add(new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, message, null));
          }
        } else {
          // Convert the data from String to the specified type ...
          //
          try {
            rowData[i] = valueMeta.convertData(stringMeta, stringValue);
          } catch (KettleValueException e) {
            switch (valueMeta.getType()) {
              case ValueMetaInterface.TYPE_NUMBER:
                {
                  String message =
                      BaseMessages.getString(
                          PKG,
                          "RowGenerator.BuildRow.Error.Parsing.Number",
                          valueMeta.getName(),
                          stringValue,
                          e.toString());
                  remarks.add(
                      new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, message, null));
                }
                break;
              case ValueMetaInterface.TYPE_DATE:
                {
                  String message =
                      BaseMessages.getString(
                          PKG,
                          "RowGenerator.BuildRow.Error.Parsing.Date",
                          valueMeta.getName(),
                          stringValue,
                          e.toString());
                  remarks.add(
                      new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, message, null));
                }
                break;
              case ValueMetaInterface.TYPE_INTEGER:
                {
                  String message =
                      BaseMessages.getString(
                          PKG,
                          "RowGenerator.BuildRow.Error.Parsing.Integer",
                          valueMeta.getName(),
                          stringValue,
                          e.toString());
                  remarks.add(
                      new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, message, null));
                }
                break;
              case ValueMetaInterface.TYPE_BIGNUMBER:
                {
                  String message =
                      BaseMessages.getString(
                          PKG,
                          "RowGenerator.BuildRow.Error.Parsing.BigNumber",
                          valueMeta.getName(),
                          stringValue,
                          e.toString());
                  remarks.add(
                      new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, message, null));
                }
                break;
              default:
                // Boolean and binary don't throw errors normally, so it's probably an unspecified
                // error problem...
                {
                  String message =
                      BaseMessages.getString(
                          PKG,
                          "RowGenerator.CheckResult.SpecifyTypeError",
                          valueMeta.getName(),
                          stringValue);
                  remarks.add(
                      new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR, message, null));
                }
                break;
            }
          }
        }
        // Now add value to the row!
        // This is in fact a copy from the fields row, but now with data.
        rowMeta.addValueMeta(valueMeta);
      }
    }

    return new RowMetaAndData(rowMeta, rowData);
  }
  public String getFieldDefinition(
      ValueMetaInterface v,
      String tk,
      String pk,
      boolean use_autoinc,
      boolean add_fieldname,
      boolean add_cr) {
    StringBuffer retval = new StringBuffer(128);

    String fieldname = v.getName();
    int length = v.getLength();
    int precision = v.getPrecision();

    if (add_fieldname) retval.append(fieldname).append(' ');

    int type = v.getType();
    switch (type) {
      case ValueMetaInterface.TYPE_DATE:
        retval.append("TIMESTAMP");
        break;
      case ValueMetaInterface.TYPE_BOOLEAN:
        if (supportsBooleanDataType()) {
          retval.append("BOOLEAN");
        } else {
          retval.append("CHAR(1)");
        }
        break;
      case ValueMetaInterface.TYPE_NUMBER:
      case ValueMetaInterface.TYPE_INTEGER:
      case ValueMetaInterface.TYPE_BIGNUMBER:
        if (fieldname.equalsIgnoreCase(tk)
            || // Technical key
            fieldname.equalsIgnoreCase(pk) // Primary key
        ) {
          retval.append(
              "BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 0, INCREMENT BY 1) PRIMARY KEY");
        } else {
          if (length > 0) {
            if (precision > 0 || length > 18) {
              retval.append("NUMERIC(").append(length).append(", ").append(precision).append(')');
            } else {
              if (length > 9) {
                retval.append("BIGINT");
              } else {
                if (length < 5) {
                  retval.append("SMALLINT");
                } else {
                  retval.append("INTEGER");
                }
              }
            }

          } else {
            retval.append("DOUBLE PRECISION");
          }
        }
        break;
      case ValueMetaInterface.TYPE_STRING:
        if (length >= DatabaseMeta.CLOB_LENGTH) {
          retval.append("TEXT");
        } else {
          retval.append("VARCHAR");
          if (length > 0) {
            retval.append('(').append(length);
          } else {
            retval.append('('); // Maybe use some default DB String length?
          }
          retval.append(')');
        }
        break;
      default:
        retval.append(" UNKNOWN");
        break;
    }

    if (add_cr) retval.append(Const.CR);

    return retval.toString();
  }