If they are defined, they can override table-level settings.
bool supportsDynamicSubcolumns() const override { return true; }
    NamesAndTypesList getVirtuals() const override;
    bool mayBenefitFromIndexForIn(const ASTPtr & left_in_operand, ContextPtr, const StorageMetadataPtr & metadata_snapshot) const override;
    
    
    struct SnapshotData : public StorageSnapshot::Data
    {
        DataPartsVector parts;
    };
    StorageSnapshotPtr getStorageSnapshot(const StorageMetadataPtr & metadata_snapshot, ContextPtr query_context) const override;
    
    void loadDataParts(bool skip_sanity_checks);
    String getLogName() const { return log_name; }
    Int64 getMaxBlockNumber() const;
    
    DataParts getDataParts(const DataPartStates & affordable_states) const;
    DataPartsVector getDataPartsVectorForInternalUsage(
        const DataPartStates & affordable_states,
        const DataPartsLock & lock,
        DataPartStateVector * out_states = nullptr,
        bool require_projection_parts = false) const;
    
    
    DataPartsVector getDataPartsVectorForInternalUsage(
        const DataPartStates & affordable_states, DataPartStateVector * out_states = nullptr, bool require_projection_parts = false) const;
    
    DataPartsVector getAllDataPartsVector(
        DataPartStateVector * out_states = nullptr,
        bool require_projection_parts = false) const;