@Override
  public void setPreparedStatementValue( DatabaseMeta databaseMeta, PreparedStatement preparedStatement, int index,
      Object data ) throws KettleDatabaseException {
    try {
      switch ( getType() ) {
        case ValueMetaInterface.TYPE_NUMBER:
          if ( !isNull( data ) ) {
            double num = getNumber( data ).doubleValue();
            if ( databaseMeta.supportsFloatRoundingOnUpdate() && getPrecision() >= 0 ) {
              num = Const.round( num, getPrecision() );
            }
            preparedStatement.setDouble( index, num );
          } else {
            preparedStatement.setNull( index, java.sql.Types.DOUBLE );
          }
          break;
        case ValueMetaInterface.TYPE_INTEGER:
          if ( !isNull( data ) ) {
            if ( databaseMeta.supportsSetLong() ) {
              preparedStatement.setLong( index, getInteger( data ).longValue() );
            } else {
              double d = getNumber( data ).doubleValue();
              if ( databaseMeta.supportsFloatRoundingOnUpdate() && getPrecision() >= 0 ) {
                preparedStatement.setDouble( index, d );
              } else {
                preparedStatement.setDouble( index, Const.round( d, getPrecision() ) );
              }
            }
          } else {
            preparedStatement.setNull( index, java.sql.Types.INTEGER );
          }
          break;
        case ValueMetaInterface.TYPE_STRING:
          if ( !isNull( data ) ) {
            if ( getLength() == DatabaseMeta.CLOB_LENGTH ) {
              setLength( databaseMeta.getMaxTextFieldLength() );
            }

            if ( getLength() <= databaseMeta.getMaxTextFieldLength() ) {
              preparedStatement.setString( index, getString( data ) );
            } else {
              String string = getString( data );

              int maxlen = databaseMeta.getMaxTextFieldLength();
              int len = string.length();

              // Take the last maxlen characters of the string...
              int begin = Math.max( len - maxlen, 0 );
              if ( begin > 0 ) {
                // Truncate if logging result if it exceeds database maximum string field length
                log.logMinimal( String.format( "Truncating %d symbols of original message in '%s' field", begin, getName() ) );
                string = string.substring( begin );
              }

              if ( databaseMeta.supportsSetCharacterStream() ) {
                preparedStatement.setCharacterStream( index, new StringReader( string ), string.length() );
              } else {
                preparedStatement.setString( index, string );
              }
            }
          } else {
            preparedStatement.setNull( index, java.sql.Types.VARCHAR );
          }
          break;
        case ValueMetaInterface.TYPE_DATE:
          if ( !isNull( data ) ) {
            // Environment variable to disable timezone setting for the database updates
            // When it is set, timezone will not be taken into account and the value will be converted
            // into the local java timezone
            if ( getPrecision() == 1 || !databaseMeta.supportsTimeStampToDateConversion() ) {
              // Convert to DATE!
              long dat = getInteger( data ).longValue(); // converts using Date.getTime()
              java.sql.Date ddate = new java.sql.Date( dat );
              if ( ignoreTimezone || this.getDateFormatTimeZone() == null ) {
                preparedStatement.setDate( index, ddate );
              } else {
                preparedStatement.setDate( index, ddate, Calendar.getInstance( this.getDateFormatTimeZone() ) );
              }
            } else {
              if ( data instanceof java.sql.Timestamp ) {
                // Preserve ns precision!
                //
                if ( ignoreTimezone || this.getDateFormatTimeZone() == null ) {
                  preparedStatement.setTimestamp( index, (java.sql.Timestamp) data );
                } else {
                  preparedStatement.setTimestamp( index, (java.sql.Timestamp) data, Calendar.getInstance( this
                      .getDateFormatTimeZone() ) );
                }
              } else {
                long dat = getInteger( data ).longValue(); // converts using Date.getTime()
                java.sql.Timestamp sdate = new java.sql.Timestamp( dat );
                if ( ignoreTimezone || this.getDateFormatTimeZone() == null ) {
                  preparedStatement.setTimestamp( index, sdate );
                } else {
                  preparedStatement.setTimestamp( index, sdate, Calendar.getInstance( this.getDateFormatTimeZone() ) );
                }
              }
            }
          } else {
            if ( getPrecision() == 1 || !databaseMeta.supportsTimeStampToDateConversion() ) {
              preparedStatement.setNull( index, java.sql.Types.DATE );
            } else {
              preparedStatement.setNull( index, java.sql.Types.TIMESTAMP );
            }
          }
          break;
        case ValueMetaInterface.TYPE_BOOLEAN:
          if ( databaseMeta.supportsBooleanDataType() ) {
            if ( !isNull( data ) ) {
              preparedStatement.setBoolean( index, getBoolean( data ).booleanValue() );
            } else {
              preparedStatement.setNull( index, java.sql.Types.BOOLEAN );
            }
          } else {
            if ( !isNull( data ) ) {
              preparedStatement.setString( index, getBoolean( data ).booleanValue() ? "Y" : "N" );
            } else {
              preparedStatement.setNull( index, java.sql.Types.CHAR );
            }
          }
          break;
        case ValueMetaInterface.TYPE_BIGNUMBER:
          if ( !isNull( data ) ) {
            preparedStatement.setBigDecimal( index, getBigNumber( data ) );
          } else {
            preparedStatement.setNull( index, java.sql.Types.DECIMAL );
          }
          break;
        case ValueMetaInterface.TYPE_BINARY:
          if ( !isNull( data ) ) {
            preparedStatement.setBytes( index, getBinary( data ) );
          } else {
            preparedStatement.setNull( index, java.sql.Types.BINARY );
          }
          break;
        default:
          // placeholder
          preparedStatement.setNull( index, java.sql.Types.VARCHAR );
          break;
      }
    } catch ( Exception e ) {
      throw new KettleDatabaseException( "Error setting value #" + index + " [" + toStringMeta()
          + "] on prepared statement", e );
    }
  }
@Test
  public void testSetPreparedStatementStringValueDontLogTruncated() throws KettleDatabaseException {
    ValueMetaBase valueMetaString = new ValueMetaBase( "LOG_FIELD", ValueMetaInterface.TYPE_STRING,  LOG_FIELD.length(), 0 );

    DatabaseMeta databaseMeta = mock( DatabaseMeta.class );
    PreparedStatement preparedStatement = mock( PreparedStatement.class );
    when( databaseMeta.getMaxTextFieldLength() ).thenReturn( LOG_FIELD.length() );
    List<KettleLoggingEvent> events = listener.getEvents();
    assertEquals( 0, events.size() );

    valueMetaString.setPreparedStatementValue( databaseMeta, preparedStatement, 0, LOG_FIELD );

    //no logging occurred as max string length equals to logging text length
    assertEquals( 0, events.size() );
  }