1 #ifndef SQL_MODE_H_INCLUDED 2 #define SQL_MODE_H_INCLUDED 3 /* 4 Copyright (c) 2019, MariaDB. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; version 2 of the License. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ 18 19 #ifdef USE_PRAGMA_INTERFACE 20 #pragma interface /* gcc class implementation */ 21 #endif 22 23 #include "sql_basic_types.h" 24 25 /* 26 class Sql_mode_dependency 27 28 A combination of hard and soft dependency on sql_mode. 29 Used to watch if a GENERATED ALWAYS AS expression guarantees consitent 30 data written to its virtual column. 31 32 A virtual column can appear in an index if: 33 - the generation expression does not depend on any sql_mode flags, or 34 - the generation expression has a soft dependency on an sql_mode flag, 35 and the column knows how to handle this dependeny. 36 37 A virtual column cannot appear in an index if: 38 - its generation expression has a hard dependency 39 - its generation expression has a soft dependency, but the column 40 cannot handle it on store. 41 An error is reported in such cases. 42 43 How dependencies appear: 44 - When a column return value depends on some sql_mode flag, 45 its Item_field adds a corresponding bit to m_soft. For example, 46 Item_field for a CHAR(N) column adds the PAD_CHAR_TO_FULL_LENGTH flag. 47 - When an SQL function/operator return value depends on some sql_mode flag, 48 it adds a corresponding bit to m_soft. For example, Item_func_minus 49 adds the MODE_NO_UNSIGNED_SUBTRACTION in case of unsigned arguments. 50 51 How dependency are processed (see examples below): 52 - All SQL functions/operators bit-OR all hard dependencies from all arguments. 53 - Some soft dependencies can be handled by the underlying Field on store, 54 e.g. CHAR(N) can handle PAD_CHAR_TO_FULL_LENGTH. 55 - Some soft dependencies can be handled by SQL functions and operators, 56 e.g. RTRIM(expr) removes expr's soft dependency on PAD_CHAR_TO_FULL_LENGTH. 57 If a function or operator handles a soft dependency on a certain sql_mode 58 flag, it removes the corresponding bit from m_soft (see below). 59 Note, m_hard is not touched in such cases. 60 - When an expression with a soft dependency on a certain sql_mode flag 61 goes as an argument to an SQL function/operator which cannot handle 62 this flag, the dependency escalates from soft to hard 63 (by moving the corresponding bit from m_soft to m_hard) and cannot be 64 handled any more on the upper level, neither by a Field on store, 65 nor by another SQL function/operator. 66 67 There are four kinds of Items: 68 1. Items that generate a soft or hard dependency, e.g. 69 - Item_field for CHAR(N) - generates soft/PAD_CHAR_TO_FULL_LENGTH 70 - Item_func_minus - generates soft/NO_UNSIGNED_SUBTRACTION 71 2. Items that convert a soft dependency to a hard dependency. 72 This happens e.g. when an Item_func instance gets a soft dependency 73 from its arguments, and it does not know how to handle this dependency. 74 Most Item_func descendants do this. 75 3. Items that remove soft dependencies, e.g.: 76 - Item_func_rtrim - removes soft/PAD_CHAR_TO_FULL_LENGTH 77 that came from args[0] (under certain conditions) 78 - Item_func_rpad - removes soft/PAD_CJAR_TO_FULL_LENGTH 79 that came from args[0] (under certain conditions) 80 4. Items that repeat soft dependency from its arguments to the caller. 81 They are not implemented yet. But functions like Item_func_coalesce, 82 Item_func_case, Item_func_case_abbreviation2 could do this. 83 84 Examples: 85 86 1. CREATE OR REPLACE TABLE t1 (a CHAR(5), v CHAR(20) AS(a), KEY(v)); 87 88 Here `v` has a soft dependency on `a`. 89 The value of `a` depends on PAD_CHAR_TO_FULL_LENGTH, it can return: 90 - 'a' - if PAD_CHAR_TO_FULL_LENGTH is disabled 91 - 'a' followed by four spaces - if PAD_CHAR_TO_FULL_LENGTH is enabled 92 But `v` will pad trailing spaces to the full length on store anyway. 93 So Field_string handles this soft dependency on store. 94 This combination of the virtial column data type and its generation 95 expression is safe and provides consistent data in `v`, which is 96 'a' followed by four spaces, no matter what PAD_CHAR_TO_FULL_LENGTH is. 97 98 2. CREATE OR REPLACE TABLE t1 (a CHAR(5), v VARCHAR(20) AS(a), KEY(v)); 99 100 Here `v` has a soft dependency on `a`. But Field_varstring does 101 not pad spaces on store, so it cannot handle this dependency. 102 This combination of the virtual column data type and its generation 103 expression is not safe. An error is returned. 104 105 3. CREATE OR REPLACE TABLE t1 (a CHAR(5), v INT AS(LENGTH(a)), KEY(v)); 106 107 Here `v` has a hard dependency on `a`, because the value of `a` 108 is wrapped to the function LENGTH(). 109 The value of `LENGTH(a)` depends on PAD_CHAR_TO_FULL_LENGTH, it can return: 110 - 1 - if PAD_CHAR_TO_FULL_LENGTH is disabled 111 - 4 - if PAD_CHAR_TO_FULL_LENGTH is enabled 112 This combination cannot provide consistent data stored to `v`, 113 therefore it's disallowed. 114 */ 115 class Sql_mode_dependency 116 { 117 sql_mode_t m_hard; 118 sql_mode_t m_soft; 119 public: Sql_mode_dependency()120 Sql_mode_dependency() 121 :m_hard(0), m_soft(0) 122 { } Sql_mode_dependency(sql_mode_t hard,sql_mode_t soft)123 Sql_mode_dependency(sql_mode_t hard, sql_mode_t soft) 124 :m_hard(hard), m_soft(soft) 125 { } hard()126 sql_mode_t hard() const { return m_hard; } soft()127 sql_mode_t soft() const { return m_soft; } 128 operator bool () const 129 { 130 return m_hard > 0 || m_soft > 0; 131 } 132 Sql_mode_dependency operator|(const Sql_mode_dependency &other) const 133 { 134 return Sql_mode_dependency(m_hard | other.m_hard, m_soft | other.m_soft); 135 } 136 Sql_mode_dependency operator&(const Sql_mode_dependency &other) const 137 { 138 return Sql_mode_dependency(m_hard & other.m_hard, m_soft & other.m_soft); 139 } 140 Sql_mode_dependency &operator|=(const Sql_mode_dependency &other) 141 { 142 m_hard|= other.m_hard; 143 m_soft|= other.m_soft; 144 return *this; 145 } 146 Sql_mode_dependency &operator&=(const Sql_mode_dependency &other) 147 { 148 m_hard&= other.m_hard; 149 m_soft&= other.m_soft; 150 return *this; 151 } soft_to_hard()152 Sql_mode_dependency &soft_to_hard() 153 { 154 m_hard|= m_soft; 155 m_soft= 0; 156 return *this; 157 } 158 void push_dependency_warnings(THD *thd); 159 }; 160 161 162 #endif // SQL_MODE_H_INCLUDED 163