public IValueMeta getValueFromSqlType()

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


  public IValueMeta getValueFromSqlType(
      IVariables variables,
      DatabaseMeta databaseMeta,
      String name,
      ResultSetMetaData rm,
      int index,
      boolean ignoreLength,
      boolean lazyConversion)
      throws HopDatabaseException {
    try {
      int length = -1;
      int precision = -1;
      int valtype = IValueMeta.TYPE_NONE;
      boolean isClob = false;

      int type = rm.getColumnType(index);
      boolean signed = false;
      try {
        signed = rm.isSigned(index);
      } catch (Exception ignored) {
        // This JDBC Driver doesn't support the isSigned method
        // nothing more we can do here by catch the exception.
      }
      switch (type) {
        case Types.CHAR, Types.VARCHAR, Types.NVARCHAR, Types.LONGVARCHAR:
          // Character Large Object
          valtype = IValueMeta.TYPE_STRING;
          if (!ignoreLength) {
            length = rm.getColumnDisplaySize(index);
          }
          break;
        case Types.CLOB, Types.NCLOB:
          valtype = IValueMeta.TYPE_STRING;
          length = DatabaseMeta.CLOB_LENGTH;
          isClob = true;
          break;

        case Types.BIGINT:
          // verify Unsigned BIGINT overflow!
          //
          if (signed) {
            valtype = IValueMeta.TYPE_INTEGER;
            precision = 0; // Max 9.223.372.036.854.775.807
            length = 15;
          } else {
            valtype = IValueMeta.TYPE_BIGNUMBER;
            precision = 0; // Max 18.446.744.073.709.551.615
            length = 16;
          }
          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 = rm.getPrecision(index);
          precision = rm.getScale(index);
          if (length >= 126) {
            length = -1;
          }
          if (precision >= 126) {
            precision = -1;
          }

          if (type == Types.DOUBLE || type == Types.FLOAT || type == 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()
                && type == 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.getIDatabase().isMySqlVariant() && precision >= length) {
              precision = -1;
              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()
              && type == 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 = rm.getScale(index);
          }
          break;

        case Types.DATE:
          if (databaseMeta.getIDatabase().isTeradataVariant()) {
            precision = 1;
          }
        case Types.TIME:
          valtype = IValueMeta.TYPE_DATE;
          //
          if (databaseMeta.getIDatabase().isMySqlVariant()) {
            String property =
                databaseMeta.getConnectionProperties(variables).getProperty("yearIsDateType");
            if (property != null
                && property.equalsIgnoreCase(CONST_FALSE)
                && rm.getColumnTypeName(index).equalsIgnoreCase("YEAR")) {
              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;

          if (databaseMeta.isDisplaySizeTwiceThePrecision()
              && (2 * rm.getPrecision(index)) == rm.getColumnDisplaySize(index)) {
            // set the length for "CHAR(X) FOR BIT DATA"
            length = rm.getPrecision(index);
          } else if ((databaseMeta.getIDatabase().isOracleVariant())
              && (type == Types.VARBINARY || type == Types.LONGVARBINARY)) {
            // set the length for Oracle "RAW" or "LONGRAW" data types
            valtype = IValueMeta.TYPE_STRING;
            length = rm.getColumnDisplaySize(index);
          } else if (databaseMeta.isMySqlVariant()
              && (type == Types.VARBINARY || type == 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 = rm.getScale(index);
          break;
      }

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

      getOriginalColumnMetadata(v, rm, index, ignoreLength);

      // See if we need to enable lazy conversion...
      //
      if (lazyConversion && valtype == IValueMeta.TYPE_STRING) {
        v.setStorageType(IValueMeta.STORAGE_TYPE_BINARY_STRING);
        // TODO set some encoding to go with this.

        // Also set the storage metadata. a copy of the parent, set to String too.
        //
        try {
          IValueMeta storageMetaData = ValueMetaFactory.cloneValueMeta(v, IValueMeta.TYPE_STRING);
          storageMetaData.setStorageType(IValueMeta.STORAGE_TYPE_NORMAL);
          v.setStorageMetadata(storageMetaData);
        } catch (Exception e) {
          throw new SQLException(e);
        }
      }

      IValueMeta newV = null;
      try {
        newV = databaseMeta.getIDatabase().customizeValueFromSqlType(v, rm, index);
      } catch (SQLException e) {
        throw new SQLException(e);
      }
      return newV == null ? v : newV;
    } catch (Exception e) {
      throw new HopDatabaseException(
          "Error determining value metadata from SQL resultset metadata", e);
    }
  }