@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;
  }
  /** Copy information from the meta-data input to the dialog fields. */
  public void getData() {
    int i;

    for (i = 0; i < input.size(); i++) {
      TableItem item = wFields.table.getItem(i);
      ValueMetaInterface v = input.getValueMeta(i);
      int idx = 1;
      if (v.getName() != null) {
        item.setText(idx++, v.getName());
      }
      item.setText(idx++, v.getTypeDesc());
      item.setText(idx++, v.getLength() < 0 ? "-" : "" + v.getLength());
      item.setText(idx++, v.getPrecision() < 0 ? "-" : "" + v.getPrecision());
      item.setText(idx++, Const.NVL(v.getOrigin(), ""));
      item.setText(idx++, ValueMeta.getStorageTypeCode(v.getStorageType()));
      item.setText(idx++, Const.NVL(v.getConversionMask(), ""));
      item.setText(idx++, Const.NVL(v.getCurrencySymbol(), ""));
      item.setText(idx++, Const.NVL(v.getDecimalSymbol(), ""));
      item.setText(idx++, Const.NVL(v.getGroupingSymbol(), ""));
      item.setText(idx++, ValueMeta.getTrimTypeDesc(v.getTrimType()));
      item.setText(idx++, Const.NVL(v.getComments(), ""));
    }
    wFields.optWidth(true);
  }
  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;
  }
  @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;
  }
  @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 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;
  }
  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();
  }