1 #ifndef SQL_TYPE_JSON_INCLUDED 2 #define SQL_TYPE_JSON_INCLUDED 3 /* 4 Copyright (c) 2019, 2021 MariaDB 5 6 This program is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License 8 as published by the Free Software Foundation; version 2 of 9 the License. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #include "mariadb.h" 22 #include "sql_type.h" 23 24 25 class Type_handler_json_common 26 { 27 public: 28 static Virtual_column_info *make_json_valid_expr(THD *thd, 29 const LEX_CSTRING *field_name); 30 static bool make_json_valid_expr_if_needed(THD *thd, Column_definition *c); set_format_name(Send_field_extended_metadata * to)31 static bool set_format_name(Send_field_extended_metadata *to) 32 { 33 static const Lex_cstring fmt(STRING_WITH_LEN("json")); 34 return to->set_format_name(fmt); 35 } 36 static const Type_handler *json_type_handler(uint max_octet_length); 37 static const Type_handler *json_blob_type_handler_by_length_bytes(uint len); 38 static const Type_handler *json_type_handler_sum(const Item_sum *sum); 39 static const Type_handler *json_type_handler_from_generic(const Type_handler *th); 40 static bool has_json_valid_constraint(const Field *field); 41 static const Type_collection *type_collection(); is_json_type_handler(const Type_handler * handler)42 static bool is_json_type_handler(const Type_handler *handler) 43 { 44 return handler->type_collection() == type_collection(); 45 } 46 }; 47 48 49 template <class BASE, const Named_type_handler<BASE> &thbase> 50 class Type_handler_general_purpose_string_to_json: 51 public BASE, 52 public Type_handler_json_common 53 { 54 public: type_handler_base()55 const Type_handler *type_handler_base() const override 56 { 57 return &thbase; 58 } type_collection()59 const Type_collection *type_collection() const override 60 { 61 return Type_handler_json_common::type_collection(); 62 } Column_definition_validate_check_constraint(THD * thd,Column_definition * c)63 bool Column_definition_validate_check_constraint(THD *thd, 64 Column_definition *c) 65 const override 66 { 67 return make_json_valid_expr_if_needed(thd, c) || 68 BASE::Column_definition_validate_check_constraint(thd, c); 69 } Column_definition_data_type_info_image(Binary_string * to,const Column_definition & def)70 bool Column_definition_data_type_info_image(Binary_string *to, 71 const Column_definition &def) 72 const override 73 { 74 /* 75 Override the inherited method to avoid JSON type handlers writing any 76 extended metadata to FRM. JSON type handlers are currently detected 77 only by CHECK(JSON_VALID()) constraint. This may change in the future 78 to do write extended metadata to FRM, for more reliable detection. 79 */ 80 return false; 81 } 82 Item_append_extended_type_info(Send_field_extended_metadata * to,const Item * item)83 bool Item_append_extended_type_info(Send_field_extended_metadata *to, 84 const Item *item) const override 85 { 86 return set_format_name(to); // Send "format=json" in the protocol 87 } 88 Item_hybrid_func_fix_attributes(THD * thd,const char * name,Type_handler_hybrid_field_type * hybrid,Type_all_attributes * attr,Item ** items,uint nitems)89 bool Item_hybrid_func_fix_attributes(THD *thd, 90 const char *name, 91 Type_handler_hybrid_field_type *hybrid, 92 Type_all_attributes *attr, 93 Item **items, uint nitems) 94 const override 95 { 96 if (BASE::Item_hybrid_func_fix_attributes(thd, name, hybrid, attr, 97 items, nitems)) 98 return true; 99 /* 100 The above call can change the type handler on "hybrid", e.g. 101 choose a proper BLOB type handler according to the calculated max_length. 102 Convert general purpose string type handler to its JSON counterpart. 103 This makes hybrid functions preserve JSON data types, e.g.: 104 COALESCE(json_expr1, json_expr2) -> JSON 105 */ 106 hybrid->set_handler(json_type_handler_from_generic(hybrid->type_handler())); 107 return false; 108 } 109 }; 110 111 112 class Type_handler_string_json: 113 public Type_handler_general_purpose_string_to_json<Type_handler_string, 114 type_handler_string> 115 { }; 116 117 118 class Type_handler_varchar_json: 119 public Type_handler_general_purpose_string_to_json<Type_handler_varchar, 120 type_handler_varchar> 121 { }; 122 123 class Type_handler_tiny_blob_json: 124 public Type_handler_general_purpose_string_to_json<Type_handler_tiny_blob, 125 type_handler_tiny_blob> 126 { }; 127 128 class Type_handler_blob_json: 129 public Type_handler_general_purpose_string_to_json<Type_handler_blob, 130 type_handler_blob> 131 { }; 132 133 134 class Type_handler_medium_blob_json: 135 public Type_handler_general_purpose_string_to_json<Type_handler_medium_blob, 136 type_handler_medium_blob> 137 { }; 138 139 class Type_handler_long_blob_json: 140 public Type_handler_general_purpose_string_to_json<Type_handler_long_blob, 141 type_handler_long_blob> 142 { }; 143 144 145 146 extern MYSQL_PLUGIN_IMPORT 147 Named_type_handler<Type_handler_string_json> type_handler_string_json; 148 149 extern MYSQL_PLUGIN_IMPORT 150 Named_type_handler<Type_handler_varchar_json> type_handler_varchar_json; 151 152 extern MYSQL_PLUGIN_IMPORT 153 Named_type_handler<Type_handler_tiny_blob_json> type_handler_tiny_blob_json; 154 155 extern MYSQL_PLUGIN_IMPORT 156 Named_type_handler<Type_handler_blob_json> type_handler_blob_json; 157 158 extern MYSQL_PLUGIN_IMPORT 159 Named_type_handler<Type_handler_medium_blob_json> type_handler_medium_blob_json; 160 161 extern MYSQL_PLUGIN_IMPORT 162 Named_type_handler<Type_handler_long_blob_json> type_handler_long_blob_json; 163 164 165 #endif // SQL_TYPE_JSON_INCLUDED 166