class DocTableRelation extends AbstractTableRelation<DocTableInfo> {

    public DocTableRelation(DocTableInfo tableInfo) {
        // System columns are excluded from `tableInfo.columns()` by default,
        // but parent relations need to be able to see them so that they're selectable.
        // E.g. in `select a._id from tbl as a`
        super(
            tableInfo,
            List.copyOf(tableInfo.columns()),
            concat(DocSysColumns.forTable(tableInfo.ident()), tableInfo.indexColumns())
        );
    }

    @Override
    public <C, R> R accept(AnalyzedRelationVisitor<C, R> visitor, C context) {
        return visitor.visitDocTableRelation(this, context);
    }

    @Nullable
    @Override
    public Reference getField(ColumnIdent path) {
        return getField(path, Operation.READ, true);
    }

    @Override
    public Reference getField(ColumnIdent column, Operation operation, boolean errorOnUnknownObjectKey)
            throws AmbiguousColumnException, ColumnUnknownException, UnsupportedOperationException {
        if (operation == Operation.UPDATE) {
            ensureColumnCanBeUpdated(column);
        }
        Reference reference = tableInfo.getReadReference(column);
        if (reference == null) {
            reference = tableInfo.indexColumn(column);
            if (reference == null) {
                reference = tableInfo.getDynamic(column,
                                                 operation == Operation.INSERT || operation == Operation.UPDATE,
                                                 errorOnUnknownObjectKey);
            }
        }
        return reference;
    }

    /**
     * @throws io.crate.exceptions.ColumnValidationException if the column cannot be updated
     */
    @VisibleForTesting
    void ensureColumnCanBeUpdated(ColumnIdent ci) {<FILL_FUNCTION_BODY>}

    private void ensureNotUpdated(ColumnIdent columnUpdated, ColumnIdent protectedColumnIdent, String errorMessage) {
        if (columnUpdated.equals(protectedColumnIdent) || protectedColumnIdent.isChildOf(columnUpdated)) {
            throw new ColumnValidationException(columnUpdated.toString(), tableInfo.ident(), errorMessage);
        }
    }
}

        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 (var 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 (var reference : generatedReference.referencedReferences()) {
                    ensureNotUpdated(ci, reference.column(),
                        "Updating a column which is referenced in a partitioned by generated column expression is not supported");
                }
            }
        }
    
<methods>public void <init>(io.crate.metadata.doc.DocTableInfo, List<io.crate.expression.symbol.Symbol>, List<io.crate.expression.symbol.Symbol>) ,public boolean equals(java.lang.Object) ,public io.crate.metadata.Reference getField(io.crate.metadata.ColumnIdent) ,public int hashCode() ,public List<io.crate.expression.symbol.Symbol> hiddenOutputs() ,public List<io.crate.expression.symbol.Symbol> outputs() ,public io.crate.metadata.RelationName relationName() ,public io.crate.metadata.Reference resolveField(io.crate.expression.symbol.ScopedSymbol) ,public io.crate.metadata.doc.DocTableInfo tableInfo() ,public java.lang.String toString() <variables>private final non-sealed List<io.crate.expression.symbol.Symbol> hiddenOutputs,private final non-sealed List<io.crate.expression.symbol.Symbol> outputs,protected final non-sealed io.crate.metadata.doc.DocTableInfo tableInfo