backend/wbprivate/sqlide/wb_live_schema_tree.h (394 lines of code) (raw):

/* * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2.0, * as published by the Free Software Foundation. * * This program is designed to work with certain software (including * but not limited to OpenSSL) that is licensed under separate terms, as * designated in a particular file or component or in included license * documentation. The authors of MySQL hereby grant you an additional * permission to link the program and your derivative works with the * separately licensed software that they have either included with * the program or referenced in the documentation. * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License, version 2.0, for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include "base/symbol-info.h" #include "grt.h" #include "grt/tree_model.h" #include "workbench/wb_backend_public_interface.h" #include "base/string_utilities.h" #include "mforms/treeview.h" #include "base/trackable.h" namespace wb { class MYSQLWBBACKEND_PUBLIC_FUNC LiveSchemaTree : base::trackable { public: friend class LiveSchemaTreeTester; static const short COLUMN_DATA; static const short TRIGGER_DATA; static const short INDEX_DATA; static const short FK_DATA; static const std::string SCHEMA_TAG; static const std::string TABLES_TAG; static const std::string VIEWS_TAG; static const std::string PROCEDURES_TAG; static const std::string FUNCTIONS_TAG; static const std::string TABLE_TAG; static const std::string VIEW_TAG; static const std::string ROUTINE_TAG; static const std::string COLUMNS_TAG; static const std::string INDEXES_TAG; static const std::string TRIGGERS_TAG; static const std::string FOREIGN_KEYS_TAG; static const std::string COLUMN_TAG; static const std::string INDEX_TAG; static const std::string TRIGGER_TAG; static const std::string FOREIGN_KEY_TAG; static const std::string FETCHING_CAPTION; static const std::string ERROR_FETCHING_CAPTION; static const std::string TABLES_CAPTION; static const std::string VIEWS_CAPTION; static const std::string PROCEDURES_CAPTION; static const std::string FUNCTIONS_CAPTION; static const std::string COLUMNS_CAPTION; static const std::string INDEXES_CAPTION; static const std::string TRIGGERS_CAPTION; static const std::string FOREIGN_KEYS_CAPTION; static const std::string LST_INFO_BOX_DETAIL_ROW; static const int TABLES_NODE_INDEX; static const int VIEWS_NODE_INDEX; static const int PROCEDURES_NODE_INDEX; static const int FUNCTIONS_NODE_INDEX; static const int TABLE_COLUMNS_NODE_INDEX; static const int TABLE_INDEXES_NODE_INDEX; static const int TABLE_FOREIGN_KEYS_NODE_INDEX; static const int TABLE_TRIGGERS_NODE_INDEX; enum FilterType { LocalLike, LocalRegexp, RemoteLike, RemoteRegexp }; enum ObjectType { Schema, Table, View, Procedure, Function, TableCollection, ViewCollection, ProcedureCollection, FunctionCollection, ColumnCollection, IndexCollection, TriggerCollection, ForeignKeyCollection, Trigger, TableColumn, ViewColumn, ForeignKey, Index, ForeignKeyColumn, IndexColumn, Any, NoneType }; // This will be used on different object type validations enum ObjectTypeValidation { DatabaseObject, // Schema, Table, View, Procedure, Function SchemaObject, // Table, View, Procedure, Function TableOrView, // Table, View ColumnObject, // TableColumn, ViewVolumn RoutineObject // Procedure, Function }; // One entry in a list that describes a single object. struct ChangeRecord { ObjectType type; std::string schema; std::string name; std::string detail; }; class MYSQLWBBACKEND_PUBLIC_FUNC LSTData : public mforms::TreeNodeData { public: std::string details; LSTData(); virtual ObjectType get_type() = 0; virtual void copy(LSTData* other); virtual std::string get_details(bool full, const mforms::TreeNodeRef& node); virtual std::string get_object_name() = 0; // Nodes requiring to enable this functionality should overwrite // and return true once their specific criteria is met virtual bool is_update_complete() { return false; } }; class MYSQLWBBACKEND_PUBLIC_FUNC ColumnData : public LSTData { private: ObjectType _type; public: ColumnData(ObjectType type = TableColumn) : LSTData(), is_pk(false), is_fk(false), is_id(false), is_idx(false) { _type = type; } // NOTE than name will contain the column name duplicating this info as it // is already on the TreeNode. Duplicating it is better than having // full HTML for all the columns on all the tables in the db. std::string name; std::string type; std::string default_value; std::string charset_collation; bool is_pk; bool is_fk; bool is_id; bool is_idx; virtual void copy(LSTData* other); virtual ObjectType get_type() { return _type; } virtual std::string get_details(bool full, const mforms::TreeNodeRef& node); virtual std::string get_object_name() { return _("Column"); } }; class MYSQLWBBACKEND_PUBLIC_FUNC FKData : public LSTData { public: FKData() : LSTData(), update_rule(0), delete_rule(0) { } unsigned char update_rule; unsigned char delete_rule; std::string referenced_table; std::string from_cols; std::string to_cols; virtual void copy(LSTData* other); virtual ObjectType get_type() { return LiveSchemaTree::ForeignKey; } virtual std::string get_details(bool full, const mforms::TreeNodeRef& node); virtual std::string get_object_name() { return _("Foreign Key"); } }; class MYSQLWBBACKEND_PUBLIC_FUNC IndexData : public LSTData { public: IndexData() : LSTData(), visible(true), unique(false), type(0) { } bool visible; bool unique; unsigned char type; std::vector<std::string> columns; virtual void copy(LSTData* other); virtual ObjectType get_type() { return LiveSchemaTree::Index; } virtual std::string get_details(bool full, const mforms::TreeNodeRef& node); virtual std::string get_object_name() { return _("Index"); } }; class MYSQLWBBACKEND_PUBLIC_FUNC TriggerData : public LSTData { public: TriggerData() : LSTData(), event_manipulation(0), timing(0) { } unsigned char event_manipulation; unsigned char timing; virtual void copy(LSTData* other); virtual ObjectType get_type() { return LiveSchemaTree::Trigger; } virtual std::string get_details(bool full, const mforms::TreeNodeRef& node); virtual std::string get_object_name() { return _("Trigger"); } }; class MYSQLWBBACKEND_PUBLIC_FUNC ObjectData : public LSTData { public: ObjectData() : LSTData(), fetched(false), fetching(false) { } bool fetched; bool fetching; virtual void copy(LSTData* other); virtual ObjectType get_type() { return LiveSchemaTree::Any; } virtual std::string get_object_name() { return _("Object"); } }; class MYSQLWBBACKEND_PUBLIC_FUNC ProcedureData : public ObjectData { public: ProcedureData() : ObjectData() { } virtual ObjectType get_type() { return LiveSchemaTree::Procedure; } virtual std::string get_object_name() { return _("Procedure"); } virtual std::string get_details(bool full, const mforms::TreeNodeRef& node); }; class MYSQLWBBACKEND_PUBLIC_FUNC FunctionData : public ObjectData { public: FunctionData() : ObjectData() { } virtual ObjectType get_type() { return LiveSchemaTree::Function; } virtual std::string get_object_name() { return _("Function"); } virtual std::string get_details(bool full, const mforms::TreeNodeRef& node); }; class MYSQLWBBACKEND_PUBLIC_FUNC ViewData : public ObjectData { public: ViewData() : ObjectData(), columns_load_error(false), _loaded_mask(0), _loading_mask(0), _reload_mask(0) { } bool columns_load_error; short _loaded_mask; short _loading_mask; short _reload_mask; virtual void copy(LSTData* other); virtual ObjectType get_type() { return LiveSchemaTree::View; } void set_reload_mask(short mask) { _reload_mask = mask; } short get_reload_mask() { return _reload_mask; } virtual short get_loaded_mask(); virtual void set_loaded_data(short mask); virtual void set_unloaded_data(short mask); bool is_data_loaded(short mask); virtual std::string get_details(bool full, const mforms::TreeNodeRef& node); virtual std::string get_object_name() { return _("View"); } short get_loading_mask(); void set_loading_mask(short mask); virtual bool is_update_complete(); }; class MYSQLWBBACKEND_PUBLIC_FUNC TableData : public ViewData { public: TableData() : ViewData() { } virtual ObjectType get_type() { return LiveSchemaTree::Table; } virtual std::string get_details(bool full, const mforms::TreeNodeRef& node); virtual std::string get_object_name() { return _("Table"); } }; class MYSQLWBBACKEND_PUBLIC_FUNC SchemaData : public LSTData { public: SchemaData() : LSTData(), fetched(false), fetching(false){}; bool fetched; bool fetching; virtual void copy(LSTData* other); virtual ObjectType get_type() { return LiveSchemaTree::Schema; } virtual std::string get_object_name() { return _("Schema"); } }; typedef std::function<void(const std::string& schema_name, base::StringListPtr tables, base::StringListPtr views, base::StringListPtr procedures, base::StringListPtr functions, bool just_append)> NewSchemaContentArrivedSlot; typedef std::function<void(const std::string& schema_name, const std::string& object_name, ObjectType obj_type, ObjectType child_type, const std::map<std::string, LSTData*>& children)> NewObjectDetailsArrivedSlot; typedef std::function<bool(mforms::TreeNodeRef, base::StringListPtr, ObjectType, bool sorted, bool just_append)> NodeChildrenUpdaterSlot; struct FetchDelegate { virtual std::vector<std::string> fetch_schema_list() = 0; virtual bool fetch_data_for_filter(const std::string&, const std::string&, const NewSchemaContentArrivedSlot&) = 0; virtual bool fetch_schema_contents(const std::string&, const NewSchemaContentArrivedSlot&) = 0; virtual bool fetch_object_details(const std::string& schema_name, const std::string& object_name, wb::LiveSchemaTree::ObjectType type, short, const NodeChildrenUpdaterSlot&) = 0; virtual bool fetch_routine_details(const std::string& schema_name, const std::string& object_name, wb::LiveSchemaTree::ObjectType type) = 0; }; struct Delegate { virtual void tree_refresh() = 0; virtual bool sidebar_action(const std::string&) = 0; virtual void tree_activate_objects(const std::string&, const std::vector<ChangeRecord>&) = 0; }; typedef boost::signals2::signal<int(const std::string&)> SqlEditorTextInsertSignal; SqlEditorTextInsertSignal sql_editor_text_insert_signal; protected: std::weak_ptr<FetchDelegate> _fetch_delegate; std::weak_ptr<Delegate> _delegate; std::string _active_schema; mforms::TreeView* _model_view; GPatternSpec* _schema_pattern = nullptr; GPatternSpec* _object_pattern = nullptr; bool _case_sensitive_identifiers; void schema_contents_arrived(const std::string& schema_name, base::StringListPtr tables, base::StringListPtr views, base::StringListPtr procedures, base::StringListPtr functions, bool just_append); void load_table_details(mforms::TreeNodeRef& node, int fetch_mask); void fetch_table_details(ObjectType object_type, const std::string schema_name, const std::string object_name, int fetch_mask); void load_routine_details(mforms::TreeNodeRef& node); void load_schema_content(mforms::TreeNodeRef& schema_node); void reload_object_data(mforms::TreeNodeRef& node); void discard_object_data(mforms::TreeNodeRef& node, int data_mask); bool identifiers_equal(const std::string& a, const std::string& b); std::vector<std::string> overlay_icons_for_tree_node(mforms::TreeNodeRef node); // Filtering functions std::string get_filter_wildcard(const std::string& filter, FilterType type = LocalLike); void clean_filter(); void filter_children_collection(mforms::TreeNodeRef& source, mforms::TreeNodeRef& target); bool filter_children(ObjectType type, mforms::TreeNodeRef& source, mforms::TreeNodeRef& target, GPatternSpec* pattern = NULL); bool is_object_type(ObjectTypeValidation validation, ObjectType type); public: LiveSchemaTree(base::MySQLVersion version); virtual ~LiveSchemaTree(); void set_model_view(mforms::TreeView* target); void set_delegate(std::shared_ptr<Delegate> delegate); void set_fetch_delegate(std::shared_ptr<FetchDelegate> delegate); void load_table_details(ObjectType object_type, const std::string schema_name, const std::string object_name, int fetch_mask); void set_filter(std::string filter); std::string getFilter() const { return _filter; } void filter_data(); void load_data_for_filter(const std::string& schema_filter, const std::string& object_filter); static unsigned char internalize_token(const std::string& token); static std::string externalize_token(unsigned char c); void set_active_schema(const std::string& schema); void set_no_connection(); void set_enabled(bool enabled); void update_live_object_state(ObjectType type, const std::string& schema_name, const std::string& old_obj_name, const std::string& new_obj_name); virtual std::string get_field_description(const mforms::TreeNodeRef& node); void set_notify_on_reload(const mforms::TreeNodeRef& node); void notify_on_reload(const mforms::TreeNodeRef& node); mforms::TreeNodeRef get_node_for_object(const std::string& schema_name, ObjectType type, const std::string& name); mforms::TreeNodeRef create_node_for_object(const std::string& schema_name, ObjectType type, const std::string& name); // Returns a list of db_query_LiveDBObjectRef. grt::BaseListRef get_selected_objects(); virtual bool activate_popup_item_for_nodes(const std::string& name, const std::list<mforms::TreeNodeRef>& orig_nodes); virtual bec::MenuItemList get_popup_items_for_nodes(const std::list<mforms::TreeNodeRef>& nodes); bool is_schema_contents_enabled() const; void is_schema_contents_enabled(bool value); void set_base(LiveSchemaTree* base) { _base = base; } LiveSchemaTree* getBase() { return _base; } bool update_node_children(mforms::TreeNodeRef parent, base::StringListPtr children, ObjectType type, bool sorted = false, bool just_append = false); void update_change_data(mforms::TreeNodeRef parent, base::StringListPtr children, ObjectType type, std::vector<mforms::TreeNodeRef>& to_remove); mforms::TreeNodeRef insert_node(mforms::TreeNodeRef parent, const std::string& name, ObjectType type); void setup_node(mforms::TreeNodeRef node, ObjectType type, mforms::TreeNodeData* data = NULL, bool ignore_null_data = false); void update_node_icon(mforms::TreeNodeRef node); void update_schemata(base::StringListPtr schema_list); mforms::TreeNodeRef binary_search_node(const mforms::TreeNodeRef& parent, int first, int last, const std::string& name, ObjectType type, int& position); mforms::TreeNodeRef get_child_node(const mforms::TreeNodeRef& parent, const std::string& name, ObjectType type = Any, bool binary_search = true); bool find_child_position(const mforms::TreeNodeRef& parent, const std::string& name, ObjectType type, int& position); void expand_toggled(mforms::TreeNodeRef node, bool value); void node_activated(mforms::TreeNodeRef node, int column); void set_case_sensitive_identifiers(bool flag); std::string get_schema_name(const mforms::TreeNodeRef& node); std::vector<std::string> get_node_path(const mforms::TreeNodeRef& node); mforms::TreeNodeRef get_node_from_path(std::vector<std::string> path); void enable_events(bool enable) { _enabled_events = enable; } bool getEnabledEvents() { return _enabled_events; } private: bool _is_schema_contents_enabled; bool _enabled_events; base::MySQLVersion _version; LiveSchemaTree *_base = nullptr; std::string _filter; ObjectType _filter_type; LSTData *notify_on_reload_data = nullptr; static const char* _schema_tokens[16]; std::map<ObjectType, std::string> _icon_paths; std::map<ObjectType, mforms::TreeNodeCollectionSkeleton> _node_collections; void fill_node_icons(); std::string get_node_icon_path(ObjectType type); bec::IconId get_node_icon(ObjectType type); }; };