/* Copyright (c) 2015, 2024, Oracle and/or its affiliates. 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 */ #ifndef DD__SDI_INCLUDED #define DD__SDI_INCLUDED #include #include #include "my_compiler.h" #include "sql/dd/sdi_fwd.h" // RJ_Document #include "sql/dd/string_type.h" // dd::String_type class THD; struct handlerton; /** @file @ingroup sdi Exposes SDI-related functionality to the rest of the dictionary code. */ namespace dd { class Schema; class Table; class Tablespace; class View; typedef String_type Sdi_type; /** The version of the current SDI Json format. This version number is stored inside SDIs. This number is bumpred only when there is a change in how the data dictionary information is converted to json (e.g. adding a forgotten member). It does not need to be bumped when the data dictionary schema structure is changed, as this is covered by the DD_VERSION variable. The SDI version number is the MySQL server version number of the first MySQL server version that published a given SDI Json format. The format is Mmmdd with M=Major, m=minor, d=dot, so that MySQL 8.0.4 is encoded as 80004. This is the same version numbering scheme as the information schema and performance schema are using. The next change to the SDI Json format will be associated with the next available MySQL server version number. Historical version number published in the data dictionary, (note that 1 is a legacy number from before SDI version numbers were mapped to server versions): 1: Published in 8.0.15 ---------------------------------------------------------------------------- Initial version. 80016: Published in 8.0.16 ---------------------------------------------------------------------------- Changes from version 1: - Bug#29210646: DD::INDEX_IMPL::M_HIDDEN NOT INCLUDED IN SDI 80019: Current ---------------------------------------------------------------------------- Changes from version 80016: - Bug#30326020: SUBPARTITIONING NOT REFLECTED IN SDI 800XX: Next SDI version number after the previous is public. The next server version > current SDI version where a change to the SDI JSON format is made. ---------------------------------------------------------------------------- Changes from current version: - No changes, this version number is not active yet. If a new SDI version is published in a MRU, it will not be possible to import this version into previous MRUs within the same GA. */ constexpr const std::uint64_t SDI_VERSION = 80019; /** @defgroup serialize_api (De)serialize api functions. @ingroup sdi Functions for serializing (with complete header) and deserializing the dd object which supports this. @{ */ /** Serialize a Schema object. @param schema dobject which will be serialized @return sdi (as json string). */ Sdi_type serialize(const Schema &schema); /** Serialize a Table object. @param thd thread context @param table object which will be serialized @param schema_name name of the schema @return sdi (as json string). */ Sdi_type serialize(THD *thd, const Table &table, const String_type &schema_name); /** Serialize a Tablespace object. @param tablespace object which will be serialized @return sdi (as json string). */ Sdi_type serialize(const Tablespace &tablespace); /** Type alias for std::function wrapping a callable to check if SDI, as an RJ_Document, is compatible. Normal MySQL error handling. Return value: false => success, true => error in DA. */ using SdiCompatibilityChecker = std::function; bool CheckDefaultCompatibility(const RJ_Document &); bool deserialize(THD *thd, const Sdi_type &sdi, Table *table, SdiCompatibilityChecker comp_checker, String_type *deser_schema_name = nullptr); /** Deserialize a dd::Table object. Populates the dd::Table object provided with data from sdi string. Note! Additional objects are dynamically allocated and added to the top-level Schema object, which assumes ownership. @note Uses the default strict compatibility checking, @see DefaultCheckCompatibility @param thd thread context @param sdi serialized representation of schema (as a json string) @param table empty top-level object @param deser_schema_name name of schema containing the table @return error status @retval false if successful @retval true otherwise */ inline bool deserialize(THD *thd, const Sdi_type &sdi, Table *table, String_type *deser_schema_name = nullptr) { return deserialize(thd, sdi, table, CheckDefaultCompatibility, deser_schema_name); } bool deserialize(THD *thd, const Sdi_type &sdi, Tablespace *tablespace, SdiCompatibilityChecker comp_checker); /** Deserialize a dd::Tablespace object. Populates the dd::Tablespace object provided with data from sdi string. Note! Additional objects are dynamically allocated and added to the top-level Tablespace object, which assumes ownership. @note Uses the default strict compatibility checking, @see DefaultCheckCompatibility @param thd thread context @param sdi serialized representation of schema (as a json string) @param tablespace empty top-level object @return error status @retval false if successful @retval true otherwise */ inline bool deserialize(THD *thd, const Sdi_type &sdi, Tablespace *tablespace) { return deserialize(thd, sdi, tablespace, CheckDefaultCompatibility); } /** @} End of group serialize_api */ namespace sdi { /** @defgroup sdi_storage_ops Storage operations on SDIs. @ingroup sdi Functions for storing and dropping (deleting) SDIs. To be used from dd::cache::Storage_adapter and dd::cache::Dictionary_client to store and remove SDIs as DD objects are added, modified or deleted. @{ */ /** Generic noop for all types that don't have a specific overload. No SDIs are written for these types. @param thd thread context @param ddo DD object @return error status @retval false always */ template inline bool store(THD *thd [[maybe_unused]], const DDT *ddo [[maybe_unused]]) { return false; } /** Stores the SDI for a table. Serializes the table, and then forwards to SE through handlerton api, or falls back to storing the sdi string in an .SDI file in the default case. The schema object is serialized and stored if the schema's SDI file does not exist, or if is missing from the tablespace used to store the table. @param thd thread context @param t Table object. @return error status @retval false on success @retval true otherwise */ bool store(THD *thd, const Table *t); /** Stores the SDI for a table space. Serializes the table space object, and then forwards to SE through handlerton api, or falls back to storing the sdi string in an .SDI file in the default case. @param thd thread context @param ts Tablespace object. @return error status @retval false on success @retval true otherwise */ bool store(THD *thd, const Tablespace *ts); /** Generic noop for all types that don't have a specific overload. No SDIs are removed for these types. @param thd thread context @return error status @retval false always */ template inline bool drop(THD *thd [[maybe_unused]], const DDT *) { return false; } /** Remove SDI for a table. Forwards to SE through handlerton api, which will remove from tablespace, or falls back to deleting the .SDI file in the default case. @param thd thread context @param t Table object. @return error status @retval false on success @retval true otherwise */ bool drop(THD *thd, const Table *t); // Note that there is NO drop() overload for Tablespace. Dropping a // tablespace implies that all sdis in it are dropped also. /** Hook for SDI cleanup after updating DD object. Generic noop for all types that don't have a specific overload. @param thd thread context @param old_ddo old DD object @param new_ddo new DD object @return error status @retval false always */ template inline bool drop_after_update(THD *thd [[maybe_unused]], const DDT *old_ddo [[maybe_unused]], const DDT *new_ddo [[maybe_unused]]) { return false; } /** Table cleanup hook. When a Dictionary_client issues a store which is performed as an update in the DD a new table SDI file will be stored. If SDI is stored in a file and the update modifies the name of the table it is necessary to remove the old SDI file after the new one has been written successfully. If the file names are the same the file is updated in place, potentially leaving it corrupted if something goes wrong. If the SDI is stored in a tablespace it will use the same key even if the names change and the update will transactional so then this hook does nothing. @param thd thread context @param old_t old Schema object @param new_t new Schema object @return error status @retval false on success @retval true otherwise */ bool drop_after_update(THD *thd, const Table *old_t, const Table *new_t); /** @} End of group sdi_storage_ops */ } // namespace sdi } // namespace dd #endif /* DD__SDI_INCLUDED */