private IndexRequest prepareInsert( DocTableInfo tableInfo, ShardUpsertRequest request, ShardUpsertRequest.Item item) throws IOException { List<GeneratedReferenceInfo> generatedReferencesWithValue = new ArrayList<>(); BytesReference source; if (request.isRawSourceInsert()) { assert item.insertValues().length > 0 : "empty insert values array"; source = new BytesArray((BytesRef) item.insertValues()[0]); } else { XContentBuilder builder = XContentFactory.jsonBuilder().startObject(); for (int i = 0; i < item.insertValues().length; i++) { Reference ref = request.insertColumns()[i]; if (ref.info().granularity() == RowGranularity.DOC) { // don't include values for partitions in the _source // ideally columns with partition granularity shouldn't be part of the request builder.field(ref.ident().columnIdent().fqn(), item.insertValues()[i]); if (ref.info() instanceof GeneratedReferenceInfo) { generatedReferencesWithValue.add((GeneratedReferenceInfo) ref.info()); } } } source = builder.bytes(); } int generatedColumnSize = 0; for (GeneratedReferenceInfo generatedReferenceInfo : tableInfo.generatedColumns()) { if (!tableInfo.partitionedByColumns().contains(generatedReferenceInfo)) { generatedColumnSize++; } } int numMissingGeneratedColumns = generatedColumnSize - generatedReferencesWithValue.size(); if (numMissingGeneratedColumns > 0 || (generatedReferencesWithValue.size() > 0 && request.validateGeneratedColumns())) { // we need to evaluate some generated column expressions Map<String, Object> sourceMap = processGeneratedColumnsOnInsert( tableInfo, request.insertColumns(), item.insertValues(), request.isRawSourceInsert(), request.validateGeneratedColumns()); source = XContentFactory.jsonBuilder().map(sourceMap).bytes(); } IndexRequest indexRequest = Requests.indexRequest(request.index()) .type(request.type()) .id(item.id()) .routing(request.routing()) .source(source) .create(!request.overwriteDuplicates()) .operationThreaded(false); if (logger.isTraceEnabled()) { logger.trace( "Inserting document with id {}, source: {}", item.id(), indexRequest.source().toUtf8()); } return indexRequest; }
private void processGeneratedColumns( final DocTableInfo tableInfo, Map<String, Object> updatedColumns, Map<String, Object> updatedGeneratedColumns, boolean validateExpressionValue, @Nullable GetResult getResult) { SymbolToFieldExtractorContext ctx = new SymbolToFieldExtractorContext(functions, updatedColumns); for (GeneratedReferenceInfo referenceInfo : tableInfo.generatedColumns()) { // partitionedBy columns cannot be updated if (!tableInfo.partitionedByColumns().contains(referenceInfo)) { Object givenValue = updatedGeneratedColumns.get(referenceInfo.ident().columnIdent().fqn()); if ((givenValue != null && validateExpressionValue) || generatedExpressionEvaluationNeeded( referenceInfo.referencedReferenceInfos(), updatedColumns.keySet())) { // at least one referenced column was updated, need to evaluate expression and update // column FieldExtractor<GetResult> extractor = SYMBOL_TO_FIELD_EXTRACTOR.convert(referenceInfo.generatedExpression(), ctx); Object value = extractor.extract(getResult); if (givenValue == null) { // add column & value updatedColumns.put(referenceInfo.ident().columnIdent().fqn(), value); } else if (validateExpressionValue && !givenValue.equals(value)) { throw new IllegalArgumentException( String.format( Locale.ENGLISH, "Given value %s for generated column does not match defined generated expression value %s", givenValue, value)); } } } } }