コード例 #1
0
ファイル: LogEventConvert.java プロジェクト: s24963386/canal
  private boolean isUpdate(List<Column> bfColumns, String newValue, int index) {
    if (bfColumns == null) {
      throw new CanalParseException("ERROR ## the bfColumns is null");
    }

    if (index < 0) {
      return false;
    }
    if ((bfColumns.size() - 1) < index) {
      return false;
    }
    Column column = bfColumns.get(index);

    if (column.getIsNull()) {
      if (newValue != null) {
        return true;
      }
    } else {
      if (newValue == null) {
        return true;
      } else {
        if (!column.getValue().equals(newValue)) {
          return true;
        }
      }
    }
    return false;
  }
コード例 #2
0
ファイル: LogEventConvert.java プロジェクト: s24963386/canal
  private void parseOneRow(
      RowData.Builder rowDataBuilder,
      RowsLogEvent event,
      RowsLogBuffer buffer,
      BitSet cols,
      boolean isAfter,
      TableMeta tableMeta)
      throws UnsupportedEncodingException {
    final int columnCnt = event.getTable().getColumnCnt();
    final ColumnInfo[] columnInfo = event.getTable().getColumnInfo();

    // check table fileds count,只能处理加字段
    if (tableMeta != null && columnInfo.length > tableMeta.getFileds().size()) {
      throw new CanalParseException(
          "column size is not match for table:" + tableMeta.getFullName());
    }

    for (int i = 0; i < columnCnt; i++) {
      ColumnInfo info = columnInfo[i];
      buffer.nextValue(info.type, info.meta);

      FieldMeta fieldMeta = null;
      Column.Builder columnBuilder = Column.newBuilder();
      columnBuilder.setIndex(i);
      columnBuilder.setIsNull(false);
      if (tableMeta != null) {
        // 处理file meta
        fieldMeta = tableMeta.getFileds().get(i);
        columnBuilder.setName(fieldMeta.getColumnName());
        columnBuilder.setIsKey(fieldMeta.isKey());
      }
      final int javaType = buffer.getJavaType();
      columnBuilder.setSqlType(javaType);
      if (buffer.isNull()) {
        columnBuilder.setIsNull(true);
      } else {
        final Serializable value = buffer.getValue();
        // 处理各种类型
        switch (javaType) {
          case Types.INTEGER:
          case Types.TINYINT:
          case Types.SMALLINT:
          case Types.BIGINT:
            // 处理unsigned类型
            Number number = (Number) value;
            if (fieldMeta != null && fieldMeta.isUnsigned() && number.longValue() < 0) {
              switch (buffer.getLength()) {
                case 1: /* MYSQL_TYPE_TINY */
                  columnBuilder.setValue(
                      String.valueOf(Integer.valueOf(TINYINT_MAX_VALUE + number.intValue())));

                case 2: /* MYSQL_TYPE_SHORT */
                  columnBuilder.setValue(
                      String.valueOf(Integer.valueOf(SMALLINT_MAX_VALUE + number.intValue())));

                case 3: /* MYSQL_TYPE_INT24 */
                  columnBuilder.setValue(
                      String.valueOf(Integer.valueOf(MEDIUMINT_MAX_VALUE + number.intValue())));

                case 4: /* MYSQL_TYPE_LONG */
                  columnBuilder.setValue(
                      String.valueOf(Long.valueOf(INTEGER_MAX_VALUE + number.longValue())));

                case 8: /* MYSQL_TYPE_LONGLONG */
                  columnBuilder.setValue(
                      BIGINT_MAX_VALUE.add(BigInteger.valueOf(number.longValue())).toString());
              }
            } else {
              // 对象为number类型,直接valueof即可
              columnBuilder.setValue(String.valueOf(value));
            }
            break;
          case Types.REAL: // float
          case Types.DOUBLE: // double
          case Types.BIT: // bit
            // 对象为number类型,直接valueof即可
            columnBuilder.setValue(String.valueOf(value));
            break;
          case Types.DECIMAL:
            columnBuilder.setValue(((BigDecimal) value).toPlainString());
            break;
          case Types.TIMESTAMP:
            String v = value.toString();
            v = v.substring(0, v.length() - 2);
            columnBuilder.setValue(v);
            break;
          case Types.TIME:
          case Types.DATE:
            // 需要处理year
            columnBuilder.setValue(value.toString());
            break;
          case Types.BINARY:
          case Types.VARBINARY:
          case Types.LONGVARBINARY:
            // fixed text encoding https://github.com/AlibabaTech/canal/issues/18
            // mysql binlog中blob/text都处理为blob类型,需要反查table meta,按编码解析text
            if (isText(fieldMeta.getColumnType())) {
              columnBuilder.setValue(new String((byte[]) value, charset));
            } else {
              // byte数组,直接使用iso-8859-1保留对应编码,浪费内存
              columnBuilder.setValue(new String((byte[]) value, ISO_8859_1));
            }
            break;
          case Types.CHAR:
          case Types.VARCHAR:
            // 本身对象为string
            columnBuilder.setValue(value.toString());
            break;
          default:
            columnBuilder.setValue(value.toString());
        }
      }

      // 设置是否update的标记位
      columnBuilder.setUpdated(
          isAfter
              && isUpdate(
                  rowDataBuilder.getBeforeColumnsList(),
                  columnBuilder.getIsNull() ? null : columnBuilder.getValue(),
                  i));
      if (isAfter) {
        rowDataBuilder.addAfterColumns(columnBuilder.build());
      } else {
        rowDataBuilder.addBeforeColumns(columnBuilder.build());
      }
    }
  }