public IValueMeta getMetadataPreview()

in core/src/main/java/org/apache/hop/core/row/value/ValueMetaBase.java [5599:5832]


  public IValueMeta getMetadataPreview(
      IVariables variables, DatabaseMeta databaseMeta, ResultSet rs) throws HopDatabaseException {

    try {
      // Get some info out of the resultset
      final String name = rs.getString("COLUMN_NAME");
      int originalColumnType = rs.getInt("DATA_TYPE");
      Object dg = rs.getObject("DECIMAL_DIGITS");
      int originalScale = dg == null ? 0 : rs.getInt("DECIMAL_DIGITS");
      int originalPrecision = rs.getInt("COLUMN_SIZE");
      int originalColumnDisplaySize = originalPrecision;
      String originalColumnTypeName = rs.getString("TYPE_NAME");
      String originalColumnLabel = rs.getString("REMARKS");
      int length = -1;
      int precision = -1;
      int valtype = IValueMeta.TYPE_NONE;
      boolean isClob = false;

      switch (originalColumnType) {
        case Types.CHAR, Types.VARCHAR, Types.NVARCHAR, Types.LONGVARCHAR:
          // Character Large Object
          valtype = IValueMeta.TYPE_STRING;
          length = originalColumnDisplaySize;
          break;

        case Types.CLOB, Types.NCLOB:
          valtype = IValueMeta.TYPE_STRING;
          length = DatabaseMeta.CLOB_LENGTH;
          isClob = true;
          break;

        case Types.BIGINT:
          // SQL BigInt is equivalent to a Java Long
          // And a Java Long is equivalent to an Apache Hop Integer.
          valtype = IValueMeta.TYPE_INTEGER;
          precision = 0; // Max 9.223.372.036.854.775.807
          length = 15;
          break;

        case Types.INTEGER:
          valtype = IValueMeta.TYPE_INTEGER;
          precision = 0; // Max 2.147.483.647
          length = 9;
          break;

        case Types.SMALLINT:
          valtype = IValueMeta.TYPE_INTEGER;
          precision = 0; // Max 32.767
          length = 4;
          break;

        case Types.TINYINT:
          valtype = IValueMeta.TYPE_INTEGER;
          precision = 0; // Max 127
          length = 2;
          break;

        case Types.DECIMAL, Types.DOUBLE, Types.FLOAT, Types.REAL, Types.NUMERIC:
          valtype = IValueMeta.TYPE_NUMBER;
          length = originalPrecision;
          precision = originalScale;
          if (length >= 126) {
            length = -1;
          }
          if (precision >= 126) {
            precision = -1;
          }

          if (originalColumnType == Types.DOUBLE
              || originalColumnType == Types.FLOAT
              || originalColumnType == Types.REAL) {
            if (precision == 0) {
              precision = -1; // precision is obviously incorrect if the type if
              // Double/Float/Real
            }

            // If we're dealing with PostgreSQL and double precision types
            if (databaseMeta.getIDatabase().isPostgresVariant()
                && originalColumnType == Types.DOUBLE
                && precision >= 16
                && length >= 16) {
              precision = -1;
              length = -1;
            }

            // MySQL: max resolution is double precision floating point (double)
            // The (12,31) that is given back is not correct
            if (databaseMeta.isMySqlVariant()) {
              if (precision >= length) {
                precision = -1;
                length = -1;
                // MySQL: Double value is giving length of 22,
                // that exceeds the maximum length.
              } else if (originalColumnType == Types.DOUBLE && length > 15) {
                length = -1;
              }
            }

            // if the length or precision needs a BIGNUMBER
            if (length > 15 || precision > 15) {
              valtype = IValueMeta.TYPE_BIGNUMBER;
            }
          } else {
            if (precision == 0) {
              if (length <= 18 && length > 0) { // Among others Oracle is affected
                // here.
                valtype = IValueMeta.TYPE_INTEGER; // Long can hold up to 18
                // significant digits
              } else if (length > 18) {
                valtype = IValueMeta.TYPE_BIGNUMBER;
              }
            } else { // we have a precision: keep NUMBER or change to BIGNUMBER?
              if (length > 15 || precision > 15) {
                valtype = IValueMeta.TYPE_BIGNUMBER;
              }
            }
          }

          if (databaseMeta.getIDatabase().isPostgresVariant()
              && originalColumnType == Types.NUMERIC
              && length == 0
              && precision == 0) {
            // undefined size => arbitrary precision
            valtype = IValueMeta.TYPE_BIGNUMBER;
            length = -1;
            precision = -1;
          }

          if (databaseMeta.getIDatabase().isOracleVariant()) {
            if (precision == 0 && length == 38) {
              valtype =
                  databaseMeta.getIDatabase().isStrictBigNumberInterpretation()
                      ? TYPE_BIGNUMBER
                      : TYPE_INTEGER;
            }
            if (precision <= 0 && length <= 0) {
              // undefined size: BIGNUMBER,
              // precision on Oracle can be 38, too
              // big for a Number type
              valtype = IValueMeta.TYPE_BIGNUMBER;
              length = -1;
              precision = -1;
            }
          }

          break;

        case Types.TIMESTAMP:
          if (databaseMeta.supportsTimestampDataType()) {
            valtype = IValueMeta.TYPE_TIMESTAMP;
            length = originalScale;
          }
          break;

        case Types.DATE:
          if (databaseMeta.getIDatabase().isTeradataVariant()) {
            precision = 1;
          }
        case Types.TIME:
          valtype = IValueMeta.TYPE_DATE;
          //
          if (databaseMeta.isMySqlVariant()) {
            String property =
                databaseMeta.getConnectionProperties(variables).getProperty("yearIsDateType");
            if (property != null
                && property.equalsIgnoreCase(CONST_FALSE)
                && "YEAR".equalsIgnoreCase(originalColumnTypeName)) {
              valtype = IValueMeta.TYPE_INTEGER;
              precision = 0;
              length = 4;
              break;
            }
          }
          break;

        case Types.BOOLEAN, Types.BIT:
          valtype = IValueMeta.TYPE_BOOLEAN;
          break;

        case Types.BINARY, Types.BLOB, Types.VARBINARY, Types.LONGVARBINARY:
          valtype = IValueMeta.TYPE_BINARY;

          IDatabase db = databaseMeta.getIDatabase();
          boolean isOracle = db.isOracleVariant();

          if (databaseMeta.isDisplaySizeTwiceThePrecision()
              && (2 * originalPrecision) == originalColumnDisplaySize) {
            // set the length for "CHAR(X) FOR BIT DATA"
            length = originalPrecision;
          } else if ((databaseMeta.getIDatabase().isOracleVariant())
              && (originalColumnType == Types.VARBINARY
                  || originalColumnType == Types.LONGVARBINARY)) {
            // set the length for Oracle "RAW" or "LONGRAW" data types
            valtype = IValueMeta.TYPE_STRING;
            length = originalColumnDisplaySize;
          } else if (databaseMeta.isMySqlVariant()
              && (originalColumnType == Types.VARBINARY
                  || originalColumnType == Types.LONGVARBINARY)) {
            // don't call 'length = rm.getColumnDisplaySize(index);'
            length = -1; // keep the length to -1, e.g. for string functions (e.g.
            // CONCAT)
          } else if (databaseMeta.getIDatabase().isSqliteVariant()) {
            valtype = IValueMeta.TYPE_STRING;
          } else {
            length = -1;
          }
          precision = -1;
          break;

        default:
          valtype = IValueMeta.TYPE_STRING;
          precision = originalScale;
          break;
      }

      IValueMeta v = ValueMetaFactory.createValueMeta(name, valtype);
      v.setLength(length);
      v.setPrecision(precision);
      v.setLargeTextField(isClob);

      // Grab the comment as a description to the field as well.
      v.setComments(originalColumnLabel);
      v.setOriginalColumnType(originalColumnType);
      v.setOriginalColumnTypeName(originalColumnTypeName);
      v.setOriginalPrecision(originalPrecision);
      v.setOriginalScale(originalScale);
      v.setOriginalSigned(originalSigned);

      return v;
    } catch (Exception e) {
      throw new HopDatabaseException(
          "Error determining value metadata from SQL resultset metadata", e);
    }
  }