All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.huaweicloud.dws.client.model.Record Maven / Gradle / Ivy

package com.huaweicloud.dws.client.model;

import com.huaweicloud.dws.client.TableConfig;
import com.huaweicloud.dws.client.exception.InvalidException;
import com.huaweicloud.dws.client.op.IConvert;
import com.huaweicloud.dws.client.util.AssertUtil;

import java.io.Serializable;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;

/**
 * @ProjectName: dws-connector
 * @ClassName: Record
 * @Description: 操作记录定义
 * @Date: 2022/12/22 18:25
 * @Version: 1.0
 */
public class Record implements Serializable {

    public static final int EMPTY = -1;
    private final TableSchema schema;
    private OperationType type = OperationType.WRITE;

    private TableConfig config;

    /**
     * 唯一KEY,避免去重时多次执行
     */
    private Record keyRecord;

    /**
     * 记录每条数据值
     */
    private final Object[] values;

    /**
     * 记录被设置过的列
     */
    private final BitSet columnBit;

    /**
     * 记录需要忽略更新的列
     */
    private final BitSet ignoreUpdate;
    private BitSet compareField;

    private IConvert dataConvert;


    /**
     * 生成该记录的数据库唯一key
     */
    public synchronized Record getRecordKey() {
        if (this.keyRecord != null) {
            return keyRecord;
        }
        keyRecord = new Record(schema, type, null);
        keyRecord.type = this.type;
        // 如果没有主键或者没设置主键(可能数据库自增),则不存在更新问题,有主键则提取主键字段
        if (!isUpsert()) {
            return this;
        }
        List keyNames = schema.getKeyIndexList();
        for (Integer index : keyNames) {
            keyRecord.setValue(index, values[index]);
        }
        return keyRecord;
    }

    /**
     * 检查是否是走upsert
     * 无主键或者自增主键返回 false
     * @return
     */
    public boolean isUpsert() {
        List keys = schema.getKeyIndexList();
        // 没有设置主键时 需要保证是自增主键才能正常入库
        return !keys.isEmpty() && EMPTY != (keys.stream().filter(this::isSet).findAny().orElse(EMPTY));
    }

    public BitSet getColumnBit() {
        return columnBit;
    }

    public BitSet getIgnoreUpdate() {
        return ignoreUpdate;
    }

    public OperationType getType() {
        return type;
    }

    public Record(TableSchema schema) {
        if (schema == null) {
            throw new InvalidException("schema is null");
        }
        this.schema = schema;
        columnBit = new BitSet(schema.getColumns().size());
        ignoreUpdate = new BitSet(schema.getColumns().size());
        values = new Object[schema.getColumns().size()];
    }

    public Record(TableSchema schema, OperationType type) {
        this(schema, type, null);
    }

    public Record(TableSchema schema, OperationType type, TableConfig config) {
        this(schema);
        if (type == null) {
            throw new InvalidException("operation type is null");
        }
        this.type = type;
        this.config = config;
        if (config != null) {
            if (this.config.getCompareField() != null) {
                this.compareField = new BitSet(schema.getColumns().size());
                for (String key : this.config.getCompareField()) {
                    Integer index = this.schema.getColumnIndex(key);
                    compareField.set(index);
                }
            }
        }
    }

    public Record(TableSchema schema, OperationType type, TableConfig config, Object[] values, BitSet columnBit, BitSet ignoreUpdate, IConvert convert) {
        this.dataConvert = convert;
        this.schema = schema;
        if (values.length > schema.getColumns().size()) {
            throw new InvalidException("values length must more dws table columns size");
        }
        this.columnBit = columnBit;
        this.ignoreUpdate = ignoreUpdate;
        if (this.schema.getColumns().size() == values.length) {
            this.values = values;
        } else {
            this.values = new Object[schema.getColumns().size()];
            System.arraycopy(values, 0, this.values, 0, values.length);
        }
        if (type == null) {
            throw new InvalidException("operation type is null");
        }
        this.type = type;
        this.config = config;
        if (config != null) {
            if (this.config.getCompareField() != null) {
                this.compareField = new BitSet(schema.getColumns().size());
                for (String key : this.config.getCompareField()) {
                    Integer index = this.schema.getColumnIndex(key);
                    compareField.set(index);
                }
            }
        }
    }

    public TableSchema getTableSchema() {
        return schema;
    }

    public Record setValue(int i, Object value) {
        return this.setValue(i, value, false);
    }

    public Record setValue(String columnName, Object value, boolean ignoreUpdate) {
        return setValue(getAndCheckIndex(columnName), value, ignoreUpdate);
    }

    public Record setValue(int i, Object value, boolean ignoreUpdate) {
        values[i] = value;
        columnBit.set(i);
        if (ignoreUpdate) {
            this.ignoreUpdate.set(i);
        }
        return this;
    }

    public Object getValue(int i) {
        return values[i];
    }

    public Object getValue(String columnName) {
        return getValue(getAndCheckIndex(columnName));
    }

    private Integer getAndCheckIndex(String columnName) {
        Integer index = schema.getColumnIndex(columnName);
        checkIdx(index);
        return index;
    }

    public boolean isSet(String name) {
        Integer i = getAndCheckIndex(name);
        return columnBit.get(i);
    }

    public boolean isSet(int index) {
        return columnBit.get(index);
    }

    public boolean isIgnoreUpdate(String name) {
        Integer i = getAndCheckIndex(name);
        return ignoreUpdate.get(i);
    }

    private void checkIdx(int i) {
        AssertUtil.isTrue(i < values.length && i >= 0, new InvalidException("not allowed i " + i));
    }

    /**
     * 用record中被设置的字段覆盖当前数据的对应字段
     */
    public void cover(Record record) {
        if (!schema.equals(record.schema)) {
            throw new InvalidException("schema not match");
        }
        if (compareField != null) {
            long count = compareField.stream().mapToObj(e -> {
                Object value = record.getValue(e);
                Object oldValue = this.getValue(e);
                return (value instanceof Comparable) && oldValue != null && ((Comparable) value).compareTo(oldValue) > 0;
            }).filter(x -> !x).count();
            if (count != 0) {
                // 当前值不比原有值大,忽略
                return;
            }
        }
        record.columnBit.stream().forEach(e -> {
            if (!record.ignoreUpdate.get(e)) {
                // 如果第二次数据标记冲突时忽略更新,则丢弃该字段二次数据
                this.setValue(e, record.getValue(e), record.ignoreUpdate.get(e));
            }
        });
    }

    public Record(TableSchema schema, OperationType type, Object[] values, BitSet columnBit,
                  BitSet ignoreUpdate) {
        this.schema = schema;
        this.type = type;
        this.values = values;
        this.columnBit = columnBit;
        this.ignoreUpdate = ignoreUpdate;
    }

    public Record copy() {
        return new Record(
                this.schema,
                this.type,
                this.values.clone(),
                (BitSet) this.columnBit.clone(),
                (BitSet) this.ignoreUpdate.clone());
    }

    public IConvert getDataConvert() {
        return dataConvert;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        } else if (!(o instanceof Record)) {
            return false;
        }
        return Arrays.deepEquals(this.values, ((Record) o).values);
    }

    @Override
    public int hashCode() {
        return Arrays.deepHashCode(this.values);
    }

    @Override
    public String toString() {
        return "Record{" +
                "schema=" + schema +
                ", values=" + Arrays.toString(values) +
                ", columnBit=" + columnBit +
                ", ignoreUpdate=" + ignoreUpdate +
                '}';
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy