예제 #1
0
  public static double toDouble(Object a) {

    double value;

    if (a instanceof java.lang.Double) {
      return ((Double) a).doubleValue();
    } else if (a instanceof BigDecimal) {
      BigDecimal bd = (BigDecimal) a;

      value = bd.doubleValue();

      int signum = bd.signum();
      BigDecimal bdd = new BigDecimal(value + signum);

      if (bdd.compareTo(bd) != signum) {
        throw Error.error(ErrorCode.X_22003);
      }
    } else if (a instanceof Number) {
      value = ((Number) a).doubleValue();
    } else {
      throw Error.error(ErrorCode.X_22501);
    }

    return value;
  }
예제 #2
0
  /**
   * Converter from a numeric object to Long. Input is checked to be within range represented by
   * Long.
   */
  static Long convertToLong(Object a) {

    if (a instanceof Integer) {
      return ValuePool.getLong(((Integer) a).intValue());
    } else if (a instanceof Long) {
      return (Long) a;
    } else if (a instanceof BigDecimal) {
      BigDecimal bd = (BigDecimal) a;

      if (bd.compareTo(MAX_LONG) > 0 || bd.compareTo(MIN_LONG) < 0) {
        throw Error.error(ErrorCode.X_22003);
      }

      return ValuePool.getLong(bd.longValue());
    } else if (a instanceof Double || a instanceof Float) {
      double d = ((Number) a).doubleValue();

      if (Double.isInfinite(d)
          || Double.isNaN(d)
          || d >= (double) Long.MAX_VALUE + 1
          || d <= (double) Long.MIN_VALUE - 1) {
        throw Error.error(ErrorCode.X_22003);
      }

      return ValuePool.getLong((long) d);
    } else {
      throw Error.error(ErrorCode.X_42561);
    }
  }
예제 #3
0
  /**
   * Converter from a numeric object to Long. Input is checked to be within range represented by
   * Long.
   */
  static Long convertToLong(SessionInterface session, Object a) {

    if (a instanceof Integer) {
      return ValuePool.getLong(((Integer) a).intValue());
    } else if (a instanceof Long) {
      return (Long) a;
    } else if (a instanceof BigDecimal) {
      BigDecimal bd = (BigDecimal) a;

      if (bd.compareTo(MAX_LONG) > 0 || bd.compareTo(MIN_LONG) < 0) {
        throw Error.error(ErrorCode.X_22003);
      }

      return ValuePool.getLong(bd.longValue());
    } else if (a instanceof Double || a instanceof Float) {
      double d = ((Number) a).doubleValue();

      if (session instanceof Session) {
        if (!((Session) session).database.sqlConvertTruncate) {
          d = java.lang.Math.rint(d);
        }
      }

      if (Double.isInfinite(d)
          || Double.isNaN(d)
          || d >= (double) Long.MAX_VALUE + 1
          || d <= (double) Long.MIN_VALUE - 1) {
        throw Error.error(ErrorCode.X_22003);
      }

      return ValuePool.getLong((long) d);
    } else {
      throw Error.error(ErrorCode.X_42561);
    }
  }
예제 #4
0
  public static NumberType getNumberType(int type, long precision, int scale) {

    switch (type) {
      case Types.SQL_INTEGER:
        return SQL_INTEGER;

      case Types.SQL_SMALLINT:
        return SQL_SMALLINT;

      case Types.SQL_BIGINT:
        return SQL_BIGINT;

      case Types.TINYINT:
        return TINYINT;

      case Types.SQL_REAL:
      case Types.SQL_DOUBLE:
      case Types.SQL_FLOAT:
        return SQL_DOUBLE;

      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
        return new NumberType(type, precision, scale);

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "NumberType");
    }
  }
예제 #5
0
  public Object floor(Object a) {

    if (a == null) {
      return null;
    }

    switch (typeCode) {
      case Types.SQL_REAL:
      case Types.SQL_FLOAT:
      case Types.SQL_DOUBLE:
        {
          double value = Math.floor(((Double) a).doubleValue());

          if (Double.isInfinite(value)) {
            throw Error.error(ErrorCode.X_22003);
          }

          return ValuePool.getDouble(Double.doubleToLongBits(value));
        }
      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
        {
          BigDecimal value = ((BigDecimal) a).setScale(0, BigDecimal.ROUND_FLOOR);

          return value;
        }

        // fall through
      default:
        return a;
    }
  }
예제 #6
0
  public boolean isNegative(Object a) {

    if (a == null) {
      return false;
    }

    switch (typeCode) {
      case Types.SQL_REAL:
      case Types.SQL_FLOAT:
      case Types.SQL_DOUBLE:
        {
          double ad = ((Number) a).doubleValue();

          return ad < 0;
        }
      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
        return ((BigDecimal) a).signum() < 0;

      case Types.TINYINT:
      case Types.SQL_SMALLINT:
      case Types.SQL_INTEGER:
        return ((Number) a).intValue() < 0;

      case Types.SQL_BIGINT:
        return ((Number) a).longValue() < 0;

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "NumberType");
    }
  }
예제 #7
0
  /**
   * relaxes the SQL standard list to avoid problems with covnersion of literals and java method
   * parameter type issues
   */
  public int precedenceDegree(Type other) {

    if (other.typeCode == typeCode) {
      return 0;
    }

    if (!other.isBinaryType()) {
      return Integer.MIN_VALUE;
    }

    switch (typeCode) {
      case Types.SQL_BIT:
      case Types.SQL_BIT_VARYING:
        return Integer.MIN_VALUE;

      case Types.SQL_BINARY:
        return other.typeCode == Types.SQL_BLOB ? 4 : 2;

      case Types.SQL_VARBINARY:
        return other.typeCode == Types.SQL_BLOB ? 4 : 2;

      case Types.SQL_BLOB:
        return other.typeCode == Types.SQL_BINARY ? -4 : -2;

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "CharacterType");
    }
  }
예제 #8
0
  /** Returns decimal precision for NUMERIC/DECIMAL. Returns binary precision for other parts. */
  public int getPrecision() {

    switch (typeCode) {
      case Types.TINYINT:
        return 1;
      case Types.SQL_SMALLINT:
        return 2;
      case Types.SQL_INTEGER:
        return 4;
      case Types.SQL_BIGINT:
        return 8;

      case Types.SQL_REAL:
      case Types.SQL_FLOAT:
      case Types.SQL_DOUBLE:
        return 8;

      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
        return (int) precision;

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "NumberType");
    }
  }
예제 #9
0
  @Override
  public String getNameString() {

    switch (typeCode) {
      case Types.TINYINT:
        return Tokens.T_TINYINT;

      case Types.SQL_SMALLINT:
        return Tokens.T_SMALLINT;

      case Types.SQL_INTEGER:
        return Tokens.T_INTEGER;

      case Types.SQL_BIGINT:
        return Tokens.T_BIGINT;

      case Types.SQL_REAL:
        return Tokens.T_REAL;

      case Types.SQL_FLOAT:
        return Tokens.T_FLOAT;

      case Types.SQL_DOUBLE:
        return Tokens.T_DOUBLE;

      case Types.SQL_NUMERIC:
        return Tokens.T_NUMERIC;

      case Types.SQL_DECIMAL:
        return Tokens.T_DECIMAL;

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "NumberType");
    }
  }
예제 #10
0
  /** Returns type for concat */
  public Type getCombinedType(Type other, int operation) {

    if (operation != OpTypes.CONCAT) {
      return getAggregateType(other);
    }

    Type newType;
    long newPrecision = this.precision + other.precision;

    switch (other.typeCode) {
      case Types.SQL_ALL_TYPES:
        return this;

      case Types.SQL_BIT:
      case Types.SQL_BIT_VARYING:
        newPrecision = this.precision + (other.precision + 7) / 8;
        newType = this;
        break;

      case Types.SQL_BINARY:
        newType = this;
        break;

      case Types.SQL_VARBINARY:
        newType = (typeCode == Types.SQL_BLOB) ? this : other;
        break;

      case Types.SQL_BLOB:
        newType = other;
        break;

      default:
        throw Error.error(ErrorCode.X_42561);
    }

    if (newPrecision > maxBinaryPrecision) {
      if (typeCode == Types.SQL_BINARY) {

        // Standard disallows type length reduction
        throw Error.error(ErrorCode.X_42570);
      } else if (typeCode == Types.SQL_VARBINARY) {
        newPrecision = maxBinaryPrecision;
      }
    }

    return getBinaryType(newType.typeCode, newPrecision);
  }
예제 #11
0
  public Object convertJavaToSQL(SessionInterface session, Object a) {

    if (a instanceof byte[]) {
      return new BinaryData((byte[]) a, true);
    }

    throw Error.error(ErrorCode.X_42561);
  }
예제 #12
0
  public final RowIterator rowIterator() {

    if (indexList.length == 0 || indexList[0] == null) {
      throw Error.runtimeError(ErrorCode.U_S0500, "RowStoreAV");
    }

    return indexList[0].firstRow(this);
  }
예제 #13
0
  public CachedObject getAccessor(Index key) {

    int position = key.getPosition();

    if (position >= accessorList.length) {
      throw Error.runtimeError(ErrorCode.U_S0500, "RowStoreAV");
    }

    return accessorList[position];
  }
예제 #14
0
  /** Returns the User object identified by the name argument. */
  public User get(String name) {

    User user = (User) userList.get(name);

    if (user == null) {
      throw Error.error(ErrorCode.X_28501, name);
    }

    return user;
  }
예제 #15
0
 static {
   try {
     BYTES_NULL = "NULL".getBytes("ISO-8859-1");
     BYTES_TRUE = "TRUE".getBytes("ISO-8859-1");
     BYTES_FALSE = "FALSE".getBytes("ISO-8859-1");
     BYTES_AND = " AND ".getBytes("ISO-8859-1");
     BYTES_IS = " IS ".getBytes("ISO-8859-1");
   } catch (UnsupportedEncodingException e) {
     Error.runtimeError(ErrorCode.U_S0500, "RowOutputTextLog");
   }
 }
예제 #16
0
  /**
   * Attempts to drop a User object with the specified name from this object's set.
   *
   * <p>A successful drop action consists of:
   *
   * <p>
   *
   * <UL>
   *   <LI>removing the User object with the specified name from the set.
   *   <LI>revoking all rights from the removed User<br>
   *       (this ensures that in case there are still references to the just dropped User object,
   *       those references cannot be used to erronously access database objects).
   * </UL>
   *
   * <p>
   */
  public void dropUser(String name) {

    boolean reservedUser = GranteeManager.isReserved(name);

    if (reservedUser) {
      throw Error.error(ErrorCode.X_28502, name);
    }

    boolean result = granteeManager.removeGrantee(name);

    if (!result) {
      throw Error.error(ErrorCode.X_28501, name);
    }

    User user = (User) userList.remove(name);

    if (user == null) {
      throw Error.error(ErrorCode.X_28501, name);
    }
  }
예제 #17
0
  /**
   * Converter from a numeric object to Integer. Input is checked to be within range represented by
   * the given number type.
   */
  static Integer convertToInt(SessionInterface session, Object a, int type) {

    int value;

    if (a instanceof Integer) {
      if (type == Types.SQL_INTEGER) {
        return (Integer) a;
      }

      value = ((Integer) a).intValue();
    } else if (a instanceof Long) {
      long temp = ((Long) a).longValue();

      if (Integer.MAX_VALUE < temp || temp < Integer.MIN_VALUE) {
        throw Error.error(ErrorCode.X_22003);
      }

      value = (int) temp;
    } else if (a instanceof BigDecimal) {
      BigDecimal bd = ((BigDecimal) a);

      if (bd.compareTo(MAX_INT) > 0 || bd.compareTo(MIN_INT) < 0) {
        throw Error.error(ErrorCode.X_22003);
      }

      value = bd.intValue();
    } else if (a instanceof Double || a instanceof Float) {
      double d = ((Number) a).doubleValue();

      if (session instanceof Session) {
        if (!((Session) session).database.sqlConvertTruncate) {
          d = java.lang.Math.rint(d);
        }
      }

      if (Double.isInfinite(d)
          || Double.isNaN(d)
          || d >= (double) Integer.MAX_VALUE + 1
          || d <= (double) Integer.MIN_VALUE - 1) {
        throw Error.error(ErrorCode.X_22003);
      }

      value = (int) d;
    } else {
      throw Error.error(ErrorCode.X_42561);
    }

    if (type == Types.TINYINT) {
      if (Byte.MAX_VALUE < value || value < Byte.MIN_VALUE) {
        throw Error.error(ErrorCode.X_22003);
      }
    } else if (type == Types.SQL_SMALLINT) {
      if (Short.MAX_VALUE < value || value < Short.MIN_VALUE) {
        throw Error.error(ErrorCode.X_22003);
      }
    }

    return Integer.valueOf(value);
  }
예제 #18
0
  /** @todo - review usage to see if range enforcement / java type conversion is necessary */
  @Override
  public Object convertToTypeLimits(SessionInterface session, Object a) {

    if (a == null) {
      return null;
    }

    switch (typeCode) {
      case Types.TINYINT:
      case Types.SQL_SMALLINT:
      case Types.SQL_INTEGER:
      case Types.SQL_BIGINT:
        return a;

      case Types.SQL_REAL:
      case Types.SQL_FLOAT:
      case Types.SQL_DOUBLE:
        return a;

      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
        BigDecimal dec = (BigDecimal) a;

        if (scale != dec.scale()) {
          dec = dec.setScale(scale, BigDecimal.ROUND_HALF_DOWN);
        }

        int valuePrecision = JavaSystem.precision(dec);

        if (valuePrecision > precision) {
          throw Error.error(ErrorCode.X_22003);
        }

        return dec;

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "NumberType");
    }
  }
예제 #19
0
  @Override
  public Object add(Object a, Object b, Type otherType) {

    if (a == null || b == null) {
      return null;
    }

    switch (typeCode) {
      case Types.SQL_REAL:
      case Types.SQL_FLOAT:
      case Types.SQL_DOUBLE:
        {
          double ad = ((Number) a).doubleValue();
          double bd = ((Number) b).doubleValue();

          return ValuePool.getDouble(Double.doubleToLongBits(ad + bd));

          //                return new Double(ad + bd);
        }
      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
        {
          a = convertToDefaultType(null, a);
          b = convertToDefaultType(null, b);

          BigDecimal abd = (BigDecimal) a;
          BigDecimal bbd = (BigDecimal) b;

          return abd.add(bbd);
        }
      case Types.TINYINT:
      case Types.SQL_SMALLINT:
      case Types.SQL_INTEGER:
        {
          int ai = ((Number) a).intValue();
          int bi = ((Number) b).intValue();

          return ValuePool.getInt(ai + bi);
        }
      case Types.SQL_BIGINT:
        {
          long longa = ((Number) a).longValue();
          long longb = ((Number) b).longValue();

          return ValuePool.getLong(longa + longb);
        }
      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "NumberType");
    }
  }
예제 #20
0
  @Override
  public Type getAggregateType(Type other) {

    if (this == other) {
      return this;
    }

    if (other.isCharacterType()) {
      return other.getAggregateType(this);
    }

    switch (other.typeCode) {
      case Types.SQL_ALL_TYPES:
        return this;

      case Types.SQL_REAL:
      case Types.SQL_FLOAT:
      case Types.SQL_DOUBLE:
      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
      case Types.TINYINT:
      case Types.SQL_SMALLINT:
      case Types.SQL_INTEGER:
      case Types.SQL_BIGINT:
        break;

      default:
        throw Error.error(ErrorCode.X_42562);
    }

    if (typeWidth == DOUBLE_WIDTH) {
      return this;
    }

    if (((NumberType) other).typeWidth == DOUBLE_WIDTH) {
      return other;
    }

    if (typeWidth <= BIGINT_WIDTH && ((NumberType) other).typeWidth <= BIGINT_WIDTH) {
      return (typeWidth > ((NumberType) other).typeWidth) ? this : other;
    }

    int newScale = scale > other.scale ? scale : other.scale;
    long newDigits =
        precision - scale > other.precision - other.scale
            ? precision - scale
            : other.precision - other.scale;

    return getNumberType(Types.SQL_DECIMAL, newDigits + newScale, newScale);
  }
예제 #21
0
  /** @todo check and adjust max precision */
  public static BinaryType getBinaryType(int type, long precision) {

    switch (type) {
      case Types.SQL_BINARY:
      case Types.SQL_VARBINARY:
        return new BinaryType(type, precision);

      case Types.SQL_BLOB:
        return new BlobType(precision);

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "BinaryType");
    }
  }
예제 #22
0
  public Object convertToDefaultType(SessionInterface session, Object a) {

    if (a == null) {
      return a;
    }

    if (a instanceof byte[]) {
      return new BinaryData((byte[]) a, false);
    } else if (a instanceof BinaryData) {
      return a;
    } else if (a instanceof String) {
      return castOrConvertToType(session, a, Type.SQL_VARCHAR, false);
    }

    throw Error.error(ErrorCode.X_22501);
  }
예제 #23
0
  /**
   * Creates a new User object under management of this object.
   *
   * <p>A set of constraints regarding user creation is imposed:
   *
   * <p>
   *
   * <OL>
   *   <LI>If the specified name is null, then an ASSERTION_FAILED exception is thrown stating that
   *       the name is null.
   *   <LI>If this object's collection already contains an element whose name attribute equals the
   *       name argument, then a GRANTEE_ALREADY_EXISTS exception is thrown. (This will catch
   *       attempts to create Reserved grantee names).
   * </OL>
   */
  public User createUser(HsqlName name, String password) {

    // This will throw an appropriate exception if grantee already exists,
    // regardless of whether the name is in any User, Role, etc. list.
    User user = granteeManager.addUser(name);

    user.setPassword(password);

    boolean success = userList.add(name.name, user);

    if (!success) {
      throw Error.error(ErrorCode.X_28503, name.statementName);
    }

    return user;
  }
예제 #24
0
  public BlobData overlay(
      Session session,
      BlobData data,
      BlobData overlay,
      long offset,
      long length,
      boolean hasLength) {

    if (data == null || overlay == null) {
      return null;
    }

    if (!hasLength) {
      length = ((BlobData) overlay).length(session);
    }

    switch (typeCode) {
      case Types.SQL_BINARY:
      case Types.SQL_VARBINARY:
        {
          BinaryData binary =
              new BinaryData(session, substring(session, data, 0, offset, true), overlay);

          binary =
              new BinaryData(session, binary, substring(session, data, offset + length, 0, false));

          return binary;
        }
      case Types.SQL_BLOB:
        {
          byte[] bytes = substring(session, data, 0, offset, false).getBytes();
          long blobLength = data.length(session) + overlay.length(session) - length;
          BlobData blob = session.createBlob(blobLength);

          blob.setBytes(session, 0, bytes);
          blob.setBytes(session, blob.length(session), overlay.getBytes());

          bytes = substring(session, data, offset + length, 0, false).getBytes();

          blob.setBytes(session, blob.length(session), bytes);

          return blob;
        }
      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "BinaryType");
    }
  }
예제 #25
0
  /**
   * Converter from a numeric object to Integer. Input is checked to be within range represented by
   * the given number type.
   */
  static Integer convertToInt(Object a, int type) {

    int value;

    if (a instanceof Integer) {
      if (type == Types.SQL_INTEGER) {
        return (Integer) a;
      }

      value = ((Integer) a).intValue();
    } else if (a instanceof Long) {
      long temp = ((Long) a).longValue();

      if (Integer.MAX_VALUE < temp || temp < Integer.MIN_VALUE) {
        throw Error.error(ErrorCode.X_22003);
      }

      value = (int) temp;
    } else if (a instanceof BigDecimal) {
      BigDecimal bd = ((BigDecimal) a);

      if (bd.compareTo(MAX_INT) > 0 || bd.compareTo(MIN_INT) < 0) {
        throw Error.error(ErrorCode.X_22003);
      }

      value = bd.intValue();
    } else if (a instanceof Double || a instanceof Float) {
      double d = ((Number) a).doubleValue();

      if (Double.isInfinite(d)
          || Double.isNaN(d)
          || d >= (double) Integer.MAX_VALUE + 1
          || d <= (double) Integer.MIN_VALUE - 1) {
        throw Error.error(ErrorCode.X_22003);
      }

      value = (int) d;
    } else {
      throw Error.error(ErrorCode.X_42561);
    }

    if (type == Types.TINYINT) {
      if (Byte.MAX_VALUE < value || value < Byte.MIN_VALUE) {
        throw Error.error(ErrorCode.X_22003);
      }
    } else if (type == Types.SQL_SMALLINT) {
      if (Short.MAX_VALUE < value || value < Short.MIN_VALUE) {
        throw Error.error(ErrorCode.X_22003);
      }
    }

    return ValuePool.getInt(value);
  }
예제 #26
0
  private static BigDecimal convertToDecimal(Object a) {

    if (a instanceof BigDecimal) {
      return (BigDecimal) a;
    } else if (a instanceof Integer || a instanceof Long) {
      return BigDecimal.valueOf(((Number) a).longValue());
    } else if (a instanceof Double) {
      double value = ((Number) a).doubleValue();

      if (Double.isInfinite(value) || Double.isNaN(value)) {
        return null;
      }

      return new BigDecimal(value);
    } else {
      throw Error.runtimeError(ErrorCode.U_S0500, "NumberType");
    }
  }
예제 #27
0
  @Override
  public int displaySize() {

    switch (typeCode) {
      case Types.SQL_DECIMAL:
      case Types.SQL_NUMERIC:
        if (scale == 0) {
          if (precision == 0) {
            return 646456995; // precision + "-.".length()}
          }

          return (int) precision + 1;
        }

        if (precision == scale) {
          return (int) precision + 3;
        }

        return (int) precision + 2;

      case Types.SQL_FLOAT:
      case Types.SQL_REAL:
      case Types.SQL_DOUBLE:
        return 23; // String.valueOf(-Double.MAX_VALUE).length();

      case Types.SQL_BIGINT:
        return 20; // decimal precision + "-".length();

      case Types.SQL_INTEGER:
        return 11; // decimal precision + "-".length();

      case Types.SQL_SMALLINT:
        return 6; // decimal precision + "-".length();

      case Types.TINYINT:
        return 4; // decimal precision + "-".length();

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "NumberType");
    }
  }
예제 #28
0
  public BlobData substring(
      SessionInterface session, BlobData data, long offset, long length, boolean hasLength) {

    long end;
    long dataLength = data.length(session);

    if (hasLength) {
      end = offset + length;
    } else {
      end = dataLength > offset ? dataLength : offset;
    }

    if (offset > end) {
      throw Error.error(ErrorCode.X_22011);
    }

    if (offset > end || end < 0) {

      // return zero length data
      offset = 0;
      end = 0;
    }

    if (offset < 0) {
      offset = 0;
    }

    if (end > dataLength) {
      end = dataLength;
    }

    length = end - offset;

    // change method signature to take long
    byte[] bytes = ((BlobData) data).getBytes(session, offset, (int) length);

    return new BinaryData(bytes, false);
  }
예제 #29
0
  @Override
  public String getJDBCClassName() {

    switch (typeCode) {
      case Types.TINYINT:
      case Types.SQL_SMALLINT:
      case Types.SQL_INTEGER:
      case Types.SQL_BIGINT:
        return "java.lang.Integer";

      case Types.SQL_REAL:
      case Types.SQL_FLOAT:
      case Types.SQL_DOUBLE:
        return "java.lang.Double";

      case Types.SQL_NUMERIC:
      case Types.SQL_DECIMAL:
        return "java.math.BigDecimal";

      default:
        throw Error.runtimeError(ErrorCode.U_S0500, "NumberType");
    }
  }
예제 #30
0
  public Object concat(Session session, Object a, Object b) {

    if (a == null || b == null) {
      return null;
    }

    long length = ((BlobData) a).length(session) + ((BlobData) b).length(session);

    if (length > precision) {
      throw Error.error(ErrorCode.X_22001);
    }

    if (typeCode == Types.SQL_BLOB) {
      BlobData blob = session.createBlob(length);

      blob.setBytes(session, 0, ((BlobData) b).getBytes());
      blob.setBytes(session, ((BlobData) a).length(session), ((BlobData) b).getBytes());

      return blob;
    } else {
      return new BinaryData(session, (BlobData) a, (BlobData) b);
    }
  }