1 /*
2    Copyright (c) 2019, 2021 MariaDB
3 
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License
6    as published by the Free Software Foundation; version 2 of
7    the License.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
17 */
18 
19 #include "sql_type_json.h"
20 #include "sql_class.h"
21 
22 
23 Named_type_handler<Type_handler_string_json>
24   type_handler_string_json("char/json");
25 
26 Named_type_handler<Type_handler_varchar_json>
27   type_handler_varchar_json("varchar/json");
28 
29 Named_type_handler<Type_handler_tiny_blob_json>
30   type_handler_tiny_blob_json("tinyblob/json");
31 
32 Named_type_handler<Type_handler_blob_json>
33   type_handler_blob_json("blob/json");
34 
35 Named_type_handler<Type_handler_medium_blob_json>
36   type_handler_medium_blob_json("mediumblob/json");
37 
38 Named_type_handler<Type_handler_long_blob_json>
39   type_handler_long_blob_json("longblob/json");
40 
41 
42 // Convert general purpose string type handlers to their JSON counterparts
43 const Type_handler *
json_type_handler_from_generic(const Type_handler * th)44 Type_handler_json_common::json_type_handler_from_generic(const Type_handler *th)
45 {
46   // Test in the order of likelyhood.
47   if (th == &type_handler_long_blob)
48     return &type_handler_long_blob_json;
49   if (th == &type_handler_varchar)
50     return &type_handler_varchar_json;
51   if (th == &type_handler_blob)
52     return &type_handler_blob_json;
53   if (th == &type_handler_tiny_blob)
54     return &type_handler_tiny_blob_json;
55   if (th == &type_handler_medium_blob)
56     return &type_handler_medium_blob_json;
57   if (th == &type_handler_string)
58     return &type_handler_string_json;
59   DBUG_ASSERT(is_json_type_handler(th));
60   return th;
61 }
62 
63 
64 /*
65   This method resembles what Type_handler::string_type_handler()
66   does for general purpose string type handlers.
67 */
68 const Type_handler *
json_type_handler(uint max_octet_length)69 Type_handler_json_common::json_type_handler(uint max_octet_length)
70 {
71   if (max_octet_length >= 16777216)
72     return &type_handler_long_blob_json;
73   else if (max_octet_length >= 65536)
74     return &type_handler_medium_blob_json;
75   else if (max_octet_length >= MAX_FIELD_VARCHARLENGTH)
76     return &type_handler_blob_json;
77   return &type_handler_varchar_json;
78 }
79 
80 
81 /*
82   This method resembles what Field_blob::type_handler()
83   does for general purpose BLOB type handlers.
84 */
85 const Type_handler *
json_blob_type_handler_by_length_bytes(uint len)86 Type_handler_json_common::json_blob_type_handler_by_length_bytes(uint len)
87 {
88   switch (len) {
89   case 1: return &type_handler_tiny_blob_json;
90   case 2: return &type_handler_blob_json;
91   case 3: return &type_handler_medium_blob_json;
92   }
93   return &type_handler_long_blob_json;
94 }
95 
96 
97 /*
98   This method resembles what Item_sum_group_concat::type_handler()
99   does for general purpose string type handlers.
100 */
101 const Type_handler *
json_type_handler_sum(const Item_sum * item)102 Type_handler_json_common::json_type_handler_sum(const Item_sum *item)
103 {
104   if (item->too_big_for_varchar())
105     return &type_handler_blob_json;
106   return &type_handler_varchar_json;
107 }
108 
109 
has_json_valid_constraint(const Field * field)110 bool Type_handler_json_common::has_json_valid_constraint(const Field *field)
111 {
112   return field->check_constraint &&
113          field->check_constraint->expr &&
114          field->check_constraint->expr->type() == Item::FUNC_ITEM &&
115          static_cast<const Item_func *>(field->check_constraint->expr)->
116            functype() == Item_func::JSON_VALID_FUNC;
117 }
118 
119 
120 /**
121    Create JSON_VALID(field_name) expression
122 */
123 
124 
125 Virtual_column_info *
make_json_valid_expr(THD * thd,const LEX_CSTRING * field_name)126 Type_handler_json_common::make_json_valid_expr(THD *thd,
127                                                const LEX_CSTRING *field_name)
128 {
129   Lex_ident_sys_st str;
130   Item *field, *expr;
131   str.set_valid_utf8(field_name);
132   if (unlikely(!(field= thd->lex->create_item_ident_field(thd,
133                                                           Lex_ident_sys(),
134                                                           Lex_ident_sys(),
135                                                           str))))
136     return 0;
137   if (unlikely(!(expr= new (thd->mem_root) Item_func_json_valid(thd, field))))
138     return 0;
139   return add_virtual_expression(thd, expr);
140 }
141 
142 
make_json_valid_expr_if_needed(THD * thd,Column_definition * c)143 bool Type_handler_json_common::make_json_valid_expr_if_needed(THD *thd,
144                                                  Column_definition *c)
145 {
146   return !c->check_constraint &&
147          !(c->check_constraint= make_json_valid_expr(thd, &c->field_name));
148 }
149 
150 
151 class Type_collection_json: public Type_collection
152 {
aggregate_common(const Type_handler * a,const Type_handler * b) const153   const Type_handler *aggregate_common(const Type_handler *a,
154                                        const Type_handler *b) const
155   {
156     if (a == b)
157       return a;
158     if (a == &type_handler_null)
159       return b;
160     if (b == &type_handler_null)
161       return a;
162     return NULL;
163   }
164 
165   /*
166     Aggregate two JSON type handlers for result.
167     If one of the handlers is not JSON, NULL is returned.
168   */
aggregate_json_for_result(const Type_handler * a,const Type_handler * b) const169   const Type_handler *aggregate_json_for_result(const Type_handler *a,
170                                                 const Type_handler *b) const
171   {
172     if (!Type_handler_json_common::is_json_type_handler(a) ||
173         !Type_handler_json_common::is_json_type_handler(b))
174       return NULL;
175     // Here we have two JSON data types. Let's aggregate their base types.
176     const Type_handler *a0= a->type_handler_base();
177     const Type_handler *b0= b->type_handler_base();
178     // Base types are expected to belong to type_collection_std:
179     DBUG_ASSERT(a0->type_collection() == type_handler_null.type_collection());
180     DBUG_ASSERT(b0->type_collection() == type_handler_null.type_collection());
181     const Type_handler *c= a0->type_collection()->aggregate_for_result(a0, b0);
182     return Type_handler_json_common::json_type_handler_from_generic(c);
183   }
184 public:
aggregate_for_result(const Type_handler * a,const Type_handler * b) const185   const Type_handler *aggregate_for_result(const Type_handler *a,
186                                            const Type_handler *b)
187                                            const override
188   {
189     const Type_handler *h;
190     if ((h= aggregate_common(a, b)) ||
191         (h= aggregate_json_for_result(a, b)))
192       return h;
193     /*
194       One of the types is not JSON.
195       Let the caller aggregate according to the derived rules:
196         COALESCE(VARCHAR/JSON, TEXT) -> COALESCE(VARCHAR, TEXT)
197     */
198     return NULL;
199   }
200 
aggregate_for_min_max(const Type_handler * a,const Type_handler * b) const201   const Type_handler *aggregate_for_min_max(const Type_handler *a,
202                                             const Type_handler *b)
203                                             const override
204   {
205     /*
206       No JSON specific rules.
207       Let the caller aggregate according to the derived rules:
208         LEAST(VARCHAR/JSON, TEXT/JSON) -> LEAST(VARCHAR, TEXT)
209     */
210     return NULL;
211   }
212 
aggregate_for_comparison(const Type_handler * a,const Type_handler * b) const213   const Type_handler *aggregate_for_comparison(const Type_handler *a,
214                                                const Type_handler *b)
215                                                const override
216   {
217     /*
218       All JSON types return &type_handler_long_blob
219       in type_handler_for_comparison(). We should not get here.
220     */
221     DBUG_ASSERT(0);
222     return NULL;
223   }
224 
aggregate_for_num_op(const Type_handler * a,const Type_handler * b) const225   const Type_handler *aggregate_for_num_op(const Type_handler *a,
226                                            const Type_handler *b)
227                                            const override
228   {
229     /*
230       No JSON specific rules.
231       Let the caller aggregate according to the derived rules:
232         (VARCHAR/JSON + TEXT/JSON) -> (VARCHAR + TEXT)
233     */
234     return NULL;
235   }
236 
handler_by_name(const LEX_CSTRING & name) const237   const Type_handler *handler_by_name(const LEX_CSTRING &name) const override
238   {
239     /*
240       Name resolution is not needed yet.
241       JSON is not fully pluggable at the moment:
242       - It is parsed using a hard-coded rule in sql_yacc.yy
243       - It does not store extended data type information into
244         FRM file yet. JSON is detected by CHECK(JSON_VALID(col))
245         and this detection is also hard-coded.
246       This will change in the future.
247     */
248     return NULL;
249   }
250 };
251 
252 
type_collection()253 const Type_collection *Type_handler_json_common::type_collection()
254 {
255   static Type_collection_json type_collection_json;
256   return &type_collection_json;
257 }
258