1 /* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #ifndef DD__OBJECT_TABLE_DEFINITION_IMPL_INCLUDED
24 #define DD__OBJECT_TABLE_DEFINITION_IMPL_INCLUDED
25 
26 #include <map>
27 #include <memory>
28 #include <vector>
29 
30 #include "my_dbug.h"
31 #include "sql/dd/string_type.h"                    // dd::String_type
32 #include "sql/dd/types/object_table_definition.h"  // dd::Object_table_definition
33 #include "sql/mysqld.h"                            // lower_case_table_names
34 
35 namespace dd {
36 
37 class Properties;
38 
39 ///////////////////////////////////////////////////////////////////////////
40 
41 class Object_table_definition_impl : public Object_table_definition {
42  public:
43   typedef std::map<String_type, int> Element_numbers;
44   typedef std::map<int, String_type> Element_definitions;
45 
46  private:
47   enum class Label {
48     NAME,
49     FIELDS,
50     INDEXES,
51     FOREIGN_KEYS,
52     OPTIONS,
53     LABEL,
54     POSITION,
55     DEFINITION,
56     ELEMENT
57   };
58 
key(Label label)59   static const char *key(Label label) {
60     switch (label) {
61       case Label::NAME:
62         return "name";
63       case Label::FIELDS:
64         return "fields";
65       case Label::INDEXES:
66         return "indexes";
67       case Label::FOREIGN_KEYS:
68         return "foreign_keys";
69       case Label::OPTIONS:
70         return "options";
71       case Label::LABEL:
72         return "lbl";
73       case Label::POSITION:
74         return "pos";
75       case Label::DEFINITION:
76         return "def";
77       case Label::ELEMENT:
78         return "elem";
79       default:
80         DBUG_ASSERT(false);
81         return "";
82     }
83   }
84 
85   static bool s_dd_tablespace_encrypted;
86 
87   String_type m_schema_name;
88   String_type m_table_name;
89 
90   String_type m_ddl_statement;
91 
92   Element_numbers m_field_numbers;
93   Element_definitions m_field_definitions;
94 
95   Element_numbers m_index_numbers;
96   Element_definitions m_index_definitions;
97 
98   Element_numbers m_foreign_key_numbers;
99   Element_definitions m_foreign_key_definitions;
100 
101   Element_numbers m_option_numbers;
102   Element_definitions m_option_definitions;
103 
104   std::vector<String_type> m_dml_statements;
105 
add_element(int element_number,const String_type & element_name,const String_type & element_definition,Element_numbers * element_numbers,Element_definitions * element_definitions)106   void add_element(int element_number, const String_type &element_name,
107                    const String_type &element_definition,
108                    Element_numbers *element_numbers,
109                    Element_definitions *element_definitions) {
110     DBUG_ASSERT(element_numbers != nullptr && element_definitions != nullptr &&
111                 element_numbers->find(element_name) == element_numbers->end() &&
112                 element_definitions->find(element_number) ==
113                     element_definitions->end());
114 
115     (*element_numbers)[element_name] = element_number;
116     (*element_definitions)[element_number] = element_definition;
117   }
118 
element_number(const String_type & element_name,const Element_numbers & element_numbers)119   int element_number(const String_type &element_name,
120                      const Element_numbers &element_numbers) const {
121     DBUG_ASSERT(element_numbers.find(element_name) != element_numbers.end());
122     return element_numbers.find(element_name)->second;
123   }
124 
125   void get_element_properties(dd::Properties *properties,
126                               const Element_numbers &element_numbers,
127                               const Element_definitions &element_defs) const;
128 
129   bool set_element_properties(const String_type &prop_str,
130                               Element_numbers *element_numbers,
131                               Element_definitions *element_defs);
132 
133  public:
Object_table_definition_impl()134   Object_table_definition_impl() {}
135 
Object_table_definition_impl(const String_type & schema_name,const String_type & table_name,const String_type & ddl_statement)136   Object_table_definition_impl(const String_type &schema_name,
137                                const String_type &table_name,
138                                const String_type &ddl_statement)
139       : m_schema_name(schema_name),
140         m_table_name(table_name),
141         m_ddl_statement(ddl_statement) {}
142 
~Object_table_definition_impl()143   virtual ~Object_table_definition_impl() {}
144 
set_dd_tablespace_encrypted(bool is_encrypted)145   static void set_dd_tablespace_encrypted(bool is_encrypted) {
146     s_dd_tablespace_encrypted = is_encrypted;
147   }
148 
is_dd_tablespace_encrypted()149   static bool is_dd_tablespace_encrypted() { return s_dd_tablespace_encrypted; }
150 
151   /**
152     Get the collation which is used for names related to the file
153     system (e.g. a schema name or table name). This collation is
154     case sensitive or not, depending on the setting of lower_case-
155     table_names.
156 
157     @return Pointer to CHARSET_INFO.
158    */
159 
fs_name_collation()160   static const CHARSET_INFO *fs_name_collation() {
161     if (lower_case_table_names == 0) return &my_charset_utf8_bin;
162     return &my_charset_utf8_tolower_ci;
163   }
164 
165   /**
166     Get the collation which is used for the name field in the table.
167     Table collation UTF8_BIN is used when collation for the name field
168     is not specified. Tables using different collation must override this
169     method.
170 
171     TODO: Changing table collation is not supporting during upgrade as of now.
172           To support this, static definition of this method should be avoided
173           and should provide a possibility to have different collations for
174           actual and target table definition.
175 
176     @return Pointer to CHARSET_INFO.
177   */
name_collation()178   static const CHARSET_INFO *name_collation() { return &my_charset_utf8_bin; }
179 
180   /**
181     Convert to lowercase if lower_case_table_names == 2. This is needed
182     e.g when reconstructing name keys from a dictionary object in order
183     to remove the object.
184 
185     @param          src  String to possibly convert to lowercase.
186     @param [in,out] buf  Buffer for storing lowercase'd string. Supplied
187                          by the caller.
188 
189     @retval  A pointer to the src string if l_c_t_n != 2
190     @retval  A pointer to the buf supplied by the caller, into which
191              the src string has been copied and lowercase'd, if l_c_t_n == 2
192    */
193 
fs_name_case(const String_type & src,char * buf)194   static const char *fs_name_case(const String_type &src, char *buf) {
195     const char *tmp_name = src.c_str();
196     if (lower_case_table_names == 2) {
197       // Lower case table names == 2 is tested on OSX.
198       /* purecov: begin tested */
199       my_stpcpy(buf, tmp_name);
200       my_casedn_str(fs_name_collation(), buf);
201       tmp_name = buf;
202       /* purecov: end */
203     }
204     return tmp_name;
205   }
206 
get_table_name()207   const String_type &get_table_name() const { return m_table_name; }
208 
set_table_name(const String_type & name)209   void set_table_name(const String_type &name) { m_table_name = name; }
210 
set_schema_name(const String_type & name)211   void set_schema_name(const String_type &name) { m_schema_name = name; }
212 
add_field(int field_number,const String_type & field_name,const String_type field_definition)213   void add_field(int field_number, const String_type &field_name,
214                  const String_type field_definition) {
215     add_element(field_number, field_name, field_definition, &m_field_numbers,
216                 &m_field_definitions);
217   }
218 
219   void add_sql_mode_field(int field_number, const String_type &field_name);
220 
add_index(int index_number,const String_type & index_name,const String_type & index_definition)221   virtual void add_index(int index_number, const String_type &index_name,
222                          const String_type &index_definition) {
223     add_element(index_number, index_name, index_definition, &m_index_numbers,
224                 &m_index_definitions);
225   }
226 
add_foreign_key(int foreign_key_number,const String_type & foreign_key_name,const String_type & foreign_key_definition)227   virtual void add_foreign_key(int foreign_key_number,
228                                const String_type &foreign_key_name,
229                                const String_type &foreign_key_definition) {
230     add_element(foreign_key_number, foreign_key_name, foreign_key_definition,
231                 &m_foreign_key_numbers, &m_foreign_key_definitions);
232   }
233 
add_option(int option_number,const String_type & option_name,const String_type & option_definition)234   virtual void add_option(int option_number, const String_type &option_name,
235                           const String_type &option_definition) {
236     add_element(option_number, option_name, option_definition,
237                 &m_option_numbers, &m_option_definitions);
238   }
239 
add_populate_statement(const String_type & statement)240   virtual void add_populate_statement(const String_type &statement) {
241     m_dml_statements.push_back(statement);
242   }
243 
field_number(const String_type & field_name)244   virtual int field_number(const String_type &field_name) const {
245     return element_number(field_name, m_field_numbers);
246   }
247 
index_number(const String_type & index_name)248   virtual int index_number(const String_type &index_name) const {
249     return element_number(index_name, m_index_numbers);
250   }
251 
option_number(const String_type & option_name)252   virtual int option_number(const String_type &option_name) const {
253     return element_number(option_name, m_option_numbers);
254   }
255 
256   virtual String_type get_ddl() const;
257 
get_dml()258   virtual const std::vector<String_type> &get_dml() const {
259     return m_dml_statements;
260   }
261 
262   virtual void store_into_properties(Properties *table_def_properties) const;
263 
restore_from_string(const String_type & ddl_statement)264   virtual bool restore_from_string(const String_type &ddl_statement) {
265     m_ddl_statement = ddl_statement;
266     return false;
267   }
268 
269   virtual bool restore_from_properties(const Properties &table_def_properties);
270 };
271 
272 ///////////////////////////////////////////////////////////////////////////
273 
274 }  // namespace dd
275 
276 #endif  // DD__OBJECT_TABLE_DEFINITION_IMPL_INCLUDED
277