private void checkCheckAndPut()

in holo-client/src/main/java/com/alibaba/hologres/client/HoloClient.java [217:274]


	private void checkCheckAndPut(CheckAndPut put) throws HoloClientException {
		if (put == null) {
			throw new HoloClientException(ExceptionCode.CONSTRAINT_VIOLATION, "CheckAndPut cannot be null");
		}
		if (put.getRecord().getSchema().getPrimaryKeys().length == 0) {
			throw new HoloClientWithDetailsException(ExceptionCode.CONSTRAINT_VIOLATION, "CheckAndPut need table have primary key:" + put.getRecord().getSchema().getTableNameObj().getFullName(), put.getRecord());
		}
		for (int index : put.getRecord().getKeyIndex()) {
			if ((!put.getRecord().isSet(index) || null == put.getRecord().getObject(index)) && put.getRecord().getSchema().getColumn(index).getDefaultValue() == null) {
				throw new HoloClientWithDetailsException(ExceptionCode.CONSTRAINT_VIOLATION, "CheckAndPut primary key cannot be null:" + put.getRecord().getSchema().getColumnSchema()[index].getName(), put.getRecord());
			}
		}
		if (put.getRecord().getSchema().isPartitionParentTable() && (!put.getRecord().isSet(put.getRecord().getSchema().getPartitionIndex()) || null == put.getRecord().getObject(put.getRecord().getSchema().getPartitionIndex()))) {
			throw new HoloClientWithDetailsException(ExceptionCode.CONSTRAINT_VIOLATION, "CheckAndPut partition key cannot be null:" + put.getRecord().getSchema().getColumnSchema()[put.getRecord().getSchema().getPartitionIndex()].getName(), put.getRecord());
		}
		if (config.getWriteMode() == WriteMode.INSERT_OR_IGNORE) {
			throw new HoloClientException(ExceptionCode.NOT_SUPPORTED, "CheckAndPut not supports writeMode insertOrIgnore.");
		}
		CheckAndPutRecord record = put.getRecord();
		String checkColumnName = record.getCheckAndPutCondition().getCheckColumnName();
		CheckCompareOp checkOp = record.getCheckAndPutCondition().getCheckOp();
		Object checkValue = record.getCheckAndPutCondition().getCheckValue();
		Object nullValue = record.getCheckAndPutCondition().getNullValue();
		Integer checkColumnIndex = record.getSchema().getColumnIndex(checkColumnName);
		if (checkColumnIndex == null || checkColumnIndex < 0) {
			throw new HoloClientWithDetailsException(ExceptionCode.INVALID_REQUEST, "checkColumn " + checkColumnName + " is not exists in table " + put.getRecord().getSchema().getTableNameObj().getFullName(), put.getRecord());
		} else {
			// CheckAndPutCondition 可能是通过columnName初始化的
			put.getRecord().getCheckAndPutCondition().setCheckColumn(record.getSchema().getColumn(checkColumnIndex));
		}

		if (checkOp == CheckCompareOp.IS_NULL || checkOp == CheckCompareOp.IS_NOT_NULL) {
			// is null,is not null不需要做coalesce,不关心nullValue,checkValue的值
			nullValue = null;
			checkValue = null;
			put.getRecord().getCheckAndPutCondition().setNullValue(nullValue);
			put.getRecord().getCheckAndPutCondition().setCheckValue(checkValue);
		} else {
			// >,>=,=,<>,<,<=操作符不能和null进行比较(结果恒为false),需要提供nullValue进行重写,相当于sql中的coalesce函数
			if (nullValue == null && record.getCheckAndPutCondition().getCheckColumn().getAllowNull()) {
				LOGGER.warn("When a field allows null, it is recommended to set nullValue to prevent null fields from being updated.");
			}
			// checkValue没有设置,表示要使用当前put中的checkColumn值和已有的值进行比较,所以Record的checkColumn必须被set
			if (checkValue == null && !put.getRecord().isSet(checkColumnIndex)) {
				throw new HoloClientWithDetailsException(ExceptionCode.INVALID_REQUEST, "checkColumn " + checkColumnName + " should be set when not set checkValue.", put.getRecord());
			}
			// checkValue没有设置,表示要使用当前put中的checkColumn值和已有的值进行比较,所以Record的checkColumn必须被set,且对于delete来说不能设置为null(抛出异常: internal error: binaryrow should not be empty)
			if (checkValue == null && put.getRecord().getObject(checkColumnIndex) == null && put.getRecord().getType() == Put.MutationType.DELETE) {
				// delete from table where (pk = $1 and $2 > checkColumn). 这里的$2不能是null
				throw new HoloClientWithDetailsException(ExceptionCode.INVALID_REQUEST, "checkColumn " + checkColumnName + " should be set not null when not set checkValue and mutationType is delete.", put.getRecord());
			}
		}
		// delete不支持攒批,直接将delete的checkValue设置为put中的checkColumn字段的值, 这样不同的Condition会分批提交
		if (checkValue == null && put.getRecord().getType() == Put.MutationType.DELETE && checkOp != CheckCompareOp.IS_NULL && checkOp != CheckCompareOp.IS_NOT_NULL) {
			checkValue = put.getRecord().getObject(checkColumnIndex);
			put.getRecord().getCheckAndPutCondition().setCheckValue(checkValue);
		}
	}