Example #1
0
  /**
   * Substitute actual data for the parameter markers to simulate parameter substitution in a
   * PreparedStatement.
   *
   * @param sql The SQL containing parameter markers to substitute.
   * @param list The parameter descriptors.
   * @param connection The current connection.
   * @return The modified SQL statement.
   */
  static String substituteParameters(String sql, ParamInfo[] list, ConnectionJDBC2 connection)
      throws SQLException {
    int len = sql.length();

    for (int i = 0; i < list.length; i++) {
      if (!list[i].isRetVal && !list[i].isSet && !list[i].isOutput) {
        throw new SQLException(
            Messages.get("error.prepare.paramnotset", Integer.toString(i + 1)), "07000");
      }

      Object value = list[i].value;

      if (value instanceof java.io.InputStream || value instanceof java.io.Reader) {
        try {
          if (list[i].jdbcType == java.sql.Types.LONGVARCHAR
              || list[i].jdbcType == java.sql.Types.CLOB
              || list[i].jdbcType == java.sql.Types.VARCHAR) {
            // TODO: Should improve the character set handling here
            value = list[i].getString("US-ASCII");
          } else {
            value = list[i].getBytes("US-ASCII");
          }
          // Replace the stream/reader with the String/byte[]
          list[i].value = value;
        } catch (java.io.IOException e) {
          throw new SQLException(Messages.get("error.generic.ioerror", e.getMessage()), "HY000");
        }
      }

      if (value instanceof String) {
        len += ((String) value).length() + 5;
      } else if (value instanceof byte[]) {
        len += ((byte[]) value).length * 2 + 4;
      } else {
        len += 32; // Default size
      }
    }

    StringBuffer buf = new StringBuffer(len + 16);
    int start = 0;

    for (int i = 0; i < list.length; i++) {
      int pos = list[i].markerPos;

      if (pos > 0) {
        buf.append(sql.substring(start, list[i].markerPos));
        start = pos + 1;
        final boolean isUnicode = connection.getTdsVersion() >= Driver.TDS70 && list[i].isUnicode;
        Support.embedData(buf, list[i].value, isUnicode, connection);
      }
    }

    if (start < sql.length()) {
      buf.append(sql.substring(start));
    }

    return buf.toString();
  }
Example #2
0
  /**
   * Embed the data object as a string literal in the buffer supplied.
   *
   * @param buf The buffer in which the data will be embedded.
   * @param value The data object.
   * @param isUnicode Set to <code>true</code> if Unicode strings should be used, else <code>false
   *     </code>.
   * @param connection The {@link ConnectionJDBC2} object.
   */
  static void embedData(
      StringBuffer buf, Object value, boolean isUnicode, ConnectionJDBC2 connection)
      throws SQLException {
    buf.append(' ');
    if (value == null) {
      buf.append("NULL ");
      return;
    }

    if (value instanceof Blob) {
      Blob blob = (Blob) value;

      value = blob.getBytes(1, (int) blob.length());
    } else if (value instanceof Clob) {
      Clob clob = (Clob) value;

      value = clob.getSubString(1, (int) clob.length());
    }

    if (value instanceof DateTime) {
      buf.append('\'');
      buf.append(value);
      buf.append('\'');
    } else if (value instanceof byte[]) {
      byte[] bytes = (byte[]) value;

      int len = bytes.length;

      if (len >= 0) {
        buf.append('0').append('x');
        if (len == 0 && connection.getTdsVersion() < Driver.TDS70) {
          // Zero length binary values are not allowed
          buf.append('0').append('0');
        } else {
          for (int i = 0; i < len; i++) {
            int b1 = bytes[i] & 0xFF;

            buf.append(hex[b1 >> 4]);
            buf.append(hex[b1 & 0x0F]);
          }
        }
      }
    } else if (value instanceof String) {
      String tmp = (String) value;
      int len = tmp.length();

      if (isUnicode) {
        buf.append('N');
      }
      buf.append('\'');

      for (int i = 0; i < len; i++) {
        char c = tmp.charAt(i);

        if (c == '\'') {
          buf.append('\'');
        }

        buf.append(c);
      }

      buf.append('\'');
    } else if (value instanceof java.sql.Date) {
      DateTime dt = new DateTime((java.sql.Date) value);
      buf.append('\'');
      buf.append(dt);
      buf.append('\'');
    } else if (value instanceof java.sql.Time) {
      DateTime dt = new DateTime((java.sql.Time) value);
      buf.append('\'');
      buf.append(dt);
      buf.append('\'');
    } else if (value instanceof java.sql.Timestamp) {
      DateTime dt = new DateTime((java.sql.Timestamp) value);
      buf.append('\'');
      buf.append(dt);
      buf.append('\'');
    } else if (value instanceof Boolean) {
      buf.append(((Boolean) value).booleanValue() ? '1' : '0');
    } else if (value instanceof BigDecimal) {
      //
      // Ensure large decimal number does not overflow the
      // maximum precision of the server.
      // Main problem is with small numbers e.g. BigDecimal(1.0).toString() =
      // 0.1000000000000000055511151231....
      //
      String tmp = value.toString();
      int maxlen = connection.getMaxPrecision();
      if (tmp.charAt(0) == '-') {
        maxlen++;
      }
      if (tmp.indexOf('.') >= 0) {
        maxlen++;
      }
      if (tmp.length() > maxlen) {
        buf.append(tmp.substring(0, maxlen));
      } else {
        buf.append(tmp);
      }
    } else {
      buf.append(value.toString());
    }
    buf.append(' ');
  }