use of io.crate.exceptions.ColumnValidationException in project crate by crate.
the class UpdateAnalyzer method analyzeAssignment.
private void analyzeAssignment(Assignment node, UpdateAnalyzedStatement.NestedAnalyzedStatement nestedAnalyzedStatement, TableInfo tableInfo, EvaluatingNormalizer normalizer, ExpressionAnalyzer expressionAnalyzer, ExpressionAnalyzer columnExpressionAnalyzer, ExpressionAnalysisContext expressionAnalysisContext, TransactionContext transactionContext) {
// unknown columns in strict objects handled in here
Reference reference = (Reference) normalizer.normalize(columnExpressionAnalyzer.convert(node.columnName(), expressionAnalysisContext), transactionContext);
final ColumnIdent ident = reference.ident().columnIdent();
if (hasMatchingParent(tableInfo, reference, IS_OBJECT_ARRAY)) {
// cannot update fields of object arrays
throw new IllegalArgumentException("Updating fields of object arrays is not supported");
}
Symbol value = normalizer.normalize(expressionAnalyzer.convert(node.expression(), expressionAnalysisContext), transactionContext);
try {
value = valueNormalizer.normalizeInputForReference(value, reference);
} catch (IllegalArgumentException | UnsupportedOperationException e) {
throw new ColumnValidationException(ident.sqlFqn(), e);
}
nestedAnalyzedStatement.addAssignment(reference, value);
}
use of io.crate.exceptions.ColumnValidationException in project crate by crate.
the class InsertFromValuesAnalyzer method addValues.
private void addValues(DocTableRelation tableRelation, ValueNormalizer valueNormalizer, EvaluatingNormalizer normalizer, ExpressionAnalyzer expressionAnalyzer, ExpressionAnalysisContext expressionAnalysisContext, TransactionContext transactionContext, ValuesResolver valuesResolver, ExpressionAnalyzer valuesAwareExpressionAnalyzer, ValuesList node, List<Assignment> assignments, InsertFromValuesAnalyzedStatement context, ReferenceToLiteralConverter.Context referenceToLiteralContext, int numPrimaryKeys, Function<List<BytesRef>, String> idFunction, int bulkIdx) throws IOException {
if (context.tableInfo().isPartitioned()) {
context.newPartitionMap();
}
List<BytesRef> primaryKeyValues = new ArrayList<>(numPrimaryKeys);
String routingValue = null;
List<ColumnIdent> primaryKey = context.tableInfo().primaryKey();
Object[] insertValues = new Object[node.values().size()];
for (int i = 0, valuesSize = node.values().size(); i < valuesSize; i++) {
Expression expression = node.values().get(i);
Symbol valuesSymbol = normalizer.normalize(expressionAnalyzer.convert(expression, expressionAnalysisContext), transactionContext);
// implicit type conversion
Reference column = context.columns().get(i);
final ColumnIdent columnIdent = column.ident().columnIdent();
Object value;
try {
valuesSymbol = valueNormalizer.normalizeInputForReference(valuesSymbol, column);
value = ((Input) valuesSymbol).value();
} catch (IllegalArgumentException | UnsupportedOperationException e) {
throw new ColumnValidationException(columnIdent.sqlFqn(), e);
} catch (ClassCastException e) {
// symbol is no Input
throw new ColumnValidationException(columnIdent.name(), SymbolFormatter.format("Invalid value '%s' in insert statement", valuesSymbol));
}
if (context.primaryKeyColumnIndices().contains(i)) {
if (value == null) {
throw new IllegalArgumentException("Primary key value must not be NULL");
}
int idx = primaryKey.indexOf(columnIdent);
if (idx < 0) {
// oh look, one or more nested primary keys!
assert value instanceof Map : "value must be instance of Map";
for (ColumnIdent pkIdent : primaryKey) {
if (!pkIdent.getRoot().equals(columnIdent)) {
continue;
}
int pkIdx = primaryKey.indexOf(pkIdent);
Object nestedValue = StringObjectMaps.fromMapByPath((Map) value, pkIdent.path());
addPrimaryKeyValue(pkIdx, nestedValue, primaryKeyValues);
}
} else {
addPrimaryKeyValue(idx, value, primaryKeyValues);
}
}
if (i == context.routingColumnIndex()) {
routingValue = extractRoutingValue(columnIdent, value, context);
}
if (context.partitionedByIndices().contains(i)) {
Object rest = processPartitionedByValues(columnIdent, value, context);
if (rest != null) {
insertValues[i] = rest;
}
} else {
insertValues[i] = value;
}
}
if (!assignments.isEmpty()) {
valuesResolver.insertValues = insertValues;
valuesResolver.columns = context.columns();
Symbol[] onDupKeyAssignments = new Symbol[assignments.size()];
valuesResolver.assignmentColumns = new ArrayList<>(assignments.size());
expressionAnalyzer.setResolveFieldsOperation(Operation.UPDATE);
for (int i = 0; i < assignments.size(); i++) {
Assignment assignment = assignments.get(i);
Reference columnName = tableRelation.resolveField((Field) expressionAnalyzer.convert(assignment.columnName(), expressionAnalysisContext));
assert columnName != null : "columnName must not be null";
Symbol valueSymbol = normalizer.normalize(valuesAwareExpressionAnalyzer.convert(assignment.expression(), expressionAnalysisContext), transactionContext);
Symbol assignmentExpression = valueNormalizer.normalizeInputForReference(valueSymbol, columnName);
onDupKeyAssignments[i] = assignmentExpression;
if (valuesResolver.assignmentColumns.size() == i) {
valuesResolver.assignmentColumns.add(columnName.ident().columnIdent().fqn());
}
}
context.addOnDuplicateKeyAssignments(onDupKeyAssignments);
context.addOnDuplicateKeyAssignmentsColumns(valuesResolver.assignmentColumns.toArray(new String[valuesResolver.assignmentColumns.size()]));
}
// process generated column expressions and add columns + values
GeneratedExpressionContext ctx = new GeneratedExpressionContext(tableRelation, context, normalizer, transactionContext, referenceToLiteralContext, primaryKeyValues, insertValues, routingValue);
processGeneratedExpressions(ctx);
insertValues = ctx.insertValues;
routingValue = ctx.routingValue;
context.sourceMaps().add(insertValues);
String id = idFunction.apply(primaryKeyValues);
context.addIdAndRouting(id, routingValue);
if (bulkIdx >= 0) {
context.bulkIndices().add(bulkIdx);
}
}
use of io.crate.exceptions.ColumnValidationException in project crate by crate.
the class ValueNormalizer method normalizeObjectValue.
@SuppressWarnings("unchecked")
private void normalizeObjectValue(Map<String, Object> value, Reference info) {
for (Map.Entry<String, Object> entry : value.entrySet()) {
AnalyzedColumnDefinition.validateName(entry.getKey());
ColumnIdent nestedIdent = ColumnIdent.getChild(info.ident().columnIdent(), entry.getKey());
TableInfo tableInfo = schemas.getTableInfo(info.ident().tableIdent());
Reference nestedInfo = tableInfo.getReference(nestedIdent);
if (nestedInfo == null) {
if (info.columnPolicy() == ColumnPolicy.IGNORED) {
continue;
}
DynamicReference dynamicReference = null;
if (tableInfo instanceof DocTableInfo) {
dynamicReference = ((DocTableInfo) tableInfo).getDynamic(nestedIdent, true);
}
if (dynamicReference == null) {
throw new ColumnUnknownException(nestedIdent.sqlFqn());
}
DataType type = DataTypes.guessType(entry.getValue());
if (type == null) {
throw new ColumnValidationException(info.ident().columnIdent().sqlFqn(), "Invalid value");
}
dynamicReference.valueType(type);
nestedInfo = dynamicReference;
} else {
if (entry.getValue() == null) {
continue;
}
}
if (nestedInfo.valueType() == DataTypes.OBJECT && entry.getValue() instanceof Map) {
normalizeObjectValue((Map<String, Object>) entry.getValue(), nestedInfo);
} else if (isObjectArray(nestedInfo.valueType()) && entry.getValue() instanceof Object[]) {
normalizeObjectArrayValue((Object[]) entry.getValue(), nestedInfo);
} else {
entry.setValue(normalizePrimitiveValue(entry.getValue(), nestedInfo));
}
}
}
use of io.crate.exceptions.ColumnValidationException in project crate by crate.
the class DocTableRelation method ensureColumnCanBeUpdated.
/**
* @throws io.crate.exceptions.ColumnValidationException if the column cannot be updated
*/
@VisibleForTesting
void ensureColumnCanBeUpdated(ColumnIdent ci) {
if (ci.isSystemColumn()) {
throw new ColumnValidationException(ci.toString(), tableInfo.ident(), "Updating a system column is not supported");
}
for (ColumnIdent pkIdent : tableInfo.primaryKey()) {
ensureNotUpdated(ci, pkIdent, "Updating a primary key is not supported");
}
if (tableInfo.clusteredBy() != null) {
ensureNotUpdated(ci, tableInfo.clusteredBy(), "Updating a clustered-by column is not supported");
}
List<GeneratedReference> generatedReferences = tableInfo.generatedColumns();
for (Reference partitionRef : tableInfo.partitionedByColumns()) {
ensureNotUpdated(ci, partitionRef.column(), "Updating a partitioned-by column is not supported");
if (!(partitionRef instanceof GeneratedReference)) {
continue;
}
int idx = generatedReferences.indexOf(partitionRef);
if (idx >= 0) {
GeneratedReference generatedReference = generatedReferences.get(idx);
for (Reference reference : generatedReference.referencedReferences()) {
ensureNotUpdated(ci, reference.column(), "Updating a column which is referenced in a partitioned by generated column expression is not supported");
}
}
}
}
use of io.crate.exceptions.ColumnValidationException in project crate by crate.
the class InsertFromValues method cast.
private static Row cast(Row row, List<Reference> columnReferences, DocTableInfo tableInfo) {
if (row == null) {
return null;
}
Object[] cells = new Object[row.numColumns()];
for (int i = 0; i < cells.length; i++) {
Reference reference = columnReferences.get(i);
DataType<?> targetType = reference.valueType();
Object value = row.get(i);
try {
cells[i] = targetType.implicitCast(value);
} catch (IllegalArgumentException | ClassCastException e) {
throw new ColumnValidationException(reference.column().name(), tableInfo.ident(), "Invalid value '" + value + "' for type '" + targetType + "'");
}
}
return new RowN(cells);
}
Aggregations