1 /* Copyright (c) 2011, Monty Program Ab
2    Copyright (c) 2011, Oleksandr Byelkin
3 
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions are
6    met:
7 
8    1. Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10 
11    2. Redistributions in binary form must the following disclaimer in
12      the documentation and/or other materials provided with the
13      distribution.
14 
15    THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY
16    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
19    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22    USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25    OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26    SUCH DAMAGE.
27 */
28 
29 #ifndef ma_dyncol_h
30 #define ma_dyncol_h
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #include <decimal.h>
36 #include <my_decimal_limits.h>
37 #include <mysql_time.h>
38 
39 #ifndef _my_sys_h
40 typedef struct st_dynamic_string
41 {
42     char *str;
43     size_t length,max_length,alloc_increment;
44 } DYNAMIC_STRING;
45 #endif
46 
47 #ifndef MY_GLOBAL_INCLUDED
48 struct st_mysql_lex_string
49 {
50   char *str;
51   size_t length;
52 };
53 typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
54 typedef struct st_mysql_lex_string LEX_STRING;
55 #endif
56 
57 /*
58   Limits of implementation
59 */
60 #define MAX_TOTAL_NAME_LENGTH 65535
61 #define MAX_NAME_LENGTH (MAX_TOTAL_NAME_LENGTH/4)
62 
63 /* NO and OK is the same used just to show semantics */
64 #define ER_DYNCOL_NO ER_DYNCOL_OK
65 
66 #ifdef HAVE_CHARSET_utf8mb4
67 #define DYNCOL_UTF (&my_charset_utf8mb4_general_ci)
68 #else
69 #define DYNCOL_UTF (&my_charset_utf8_general_ci)
70 #endif
71 
72 /* escape json strings */
73 #define DYNCOL_JSON_ESC ((char)1)
74 
75 enum enum_dyncol_func_result
76 {
77   ER_DYNCOL_OK= 0,
78   ER_DYNCOL_YES= 1,                /* For functions returning 0/1 */
79   ER_DYNCOL_FORMAT= -1,            /* Wrong format of the encoded string */
80   ER_DYNCOL_LIMIT=  -2,            /* Some limit reached */
81   ER_DYNCOL_RESOURCE= -3,          /* Out of resourses */
82   ER_DYNCOL_DATA= -4,              /* Incorrect input data */
83   ER_DYNCOL_UNKNOWN_CHARSET= -5,   /* Unknown character set */
84   ER_DYNCOL_TRUNCATED= 2           /* OK, but data was truncated */
85 };
86 
87 typedef DYNAMIC_STRING DYNAMIC_COLUMN;
88 
89 enum enum_dynamic_column_type
90 {
91   DYN_COL_NULL= 0,
92   DYN_COL_INT,
93   DYN_COL_UINT,
94   DYN_COL_DOUBLE,
95   DYN_COL_STRING,
96   DYN_COL_DECIMAL,
97   DYN_COL_DATETIME,
98   DYN_COL_DATE,
99   DYN_COL_TIME,
100   DYN_COL_DYNCOL
101 };
102 
103 typedef enum enum_dynamic_column_type DYNAMIC_COLUMN_TYPE;
104 
105 struct st_dynamic_column_value
106 {
107   DYNAMIC_COLUMN_TYPE type;
108   union
109   {
110     long long long_value;
111     unsigned long long ulong_value;
112     double double_value;
113     struct {
114       MYSQL_LEX_STRING value;
115       CHARSET_INFO *charset;
116     } string;
117     struct {
118       decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
119       decimal_t value;
120     } decimal;
121     MYSQL_TIME time_value;
122   } x;
123 };
124 
125 typedef struct st_dynamic_column_value DYNAMIC_COLUMN_VALUE;
126 
127 #ifdef MADYNCOL_DEPRECATED
128 enum enum_dyncol_func_result
129 dynamic_column_create(DYNAMIC_COLUMN *str,
130                       uint column_nr, DYNAMIC_COLUMN_VALUE *value);
131 
132 enum enum_dyncol_func_result
133 dynamic_column_create_many(DYNAMIC_COLUMN *str,
134                            uint column_count,
135                            uint *column_numbers,
136                            DYNAMIC_COLUMN_VALUE *values);
137 enum enum_dyncol_func_result
138 dynamic_column_update(DYNAMIC_COLUMN *org, uint column_nr,
139                       DYNAMIC_COLUMN_VALUE *value);
140 enum enum_dyncol_func_result
141 dynamic_column_update_many(DYNAMIC_COLUMN *str,
142                            uint add_column_count,
143                            uint *column_numbers,
144                            DYNAMIC_COLUMN_VALUE *values);
145 
146 enum enum_dyncol_func_result
147 dynamic_column_exists(DYNAMIC_COLUMN *org, uint column_nr);
148 
149 enum enum_dyncol_func_result
150 dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint);
151 
152 enum enum_dyncol_func_result
153 dynamic_column_get(DYNAMIC_COLUMN *org, uint column_nr,
154                    DYNAMIC_COLUMN_VALUE *store_it_here);
155 #endif
156 
157 /* new functions */
158 enum enum_dyncol_func_result
159 mariadb_dyncol_create_many_num(DYNAMIC_COLUMN *str,
160                                uint column_count,
161                                uint *column_numbers,
162                                DYNAMIC_COLUMN_VALUE *values,
163                                my_bool new_string);
164 enum enum_dyncol_func_result
165 mariadb_dyncol_create_many_named(DYNAMIC_COLUMN *str,
166                                  uint column_count,
167                                  MYSQL_LEX_STRING *column_keys,
168                                  DYNAMIC_COLUMN_VALUE *values,
169                                  my_bool new_string);
170 
171 
172 enum enum_dyncol_func_result
173 mariadb_dyncol_update_many_num(DYNAMIC_COLUMN *str,
174                                uint add_column_count,
175                                uint *column_keys,
176                                DYNAMIC_COLUMN_VALUE *values);
177 enum enum_dyncol_func_result
178 mariadb_dyncol_update_many_named(DYNAMIC_COLUMN *str,
179                                  uint add_column_count,
180                                  MYSQL_LEX_STRING *column_keys,
181                                  DYNAMIC_COLUMN_VALUE *values);
182 
183 
184 enum enum_dyncol_func_result
185 mariadb_dyncol_exists_num(DYNAMIC_COLUMN *org, uint column_nr);
186 enum enum_dyncol_func_result
187 mariadb_dyncol_exists_named(DYNAMIC_COLUMN *str, MYSQL_LEX_STRING *name);
188 
189 /* List of not NULL columns */
190 enum enum_dyncol_func_result
191 mariadb_dyncol_list_num(DYNAMIC_COLUMN *str, uint *count, uint **nums);
192 enum enum_dyncol_func_result
193 mariadb_dyncol_list_named(DYNAMIC_COLUMN *str, uint *count,
194                           MYSQL_LEX_STRING **names);
195 
196 /*
197    if the column do not exists it is NULL
198 */
199 enum enum_dyncol_func_result
200 mariadb_dyncol_get_num(DYNAMIC_COLUMN *org, uint column_nr,
201                        DYNAMIC_COLUMN_VALUE *store_it_here);
202 enum enum_dyncol_func_result
203 mariadb_dyncol_get_named(DYNAMIC_COLUMN *str, MYSQL_LEX_STRING *name,
204                          DYNAMIC_COLUMN_VALUE *store_it_here);
205 
206 my_bool mariadb_dyncol_has_names(DYNAMIC_COLUMN *str);
207 
208 enum enum_dyncol_func_result
209 mariadb_dyncol_check(DYNAMIC_COLUMN *str);
210 
211 enum enum_dyncol_func_result
212 mariadb_dyncol_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json);
213 
214 #define mariadb_dyncol_init(A) memset((A), 0, sizeof(*(A)))
215 void mariadb_dyncol_free(DYNAMIC_COLUMN *str);
216 
217 /* conversion of values to 3 base types */
218 enum enum_dyncol_func_result
219 mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
220                        CHARSET_INFO *cs, my_bool quote);
221 enum enum_dyncol_func_result
222 mariadb_dyncol_val_long(longlong *ll, DYNAMIC_COLUMN_VALUE *val);
223 enum enum_dyncol_func_result
224 mariadb_dyncol_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val);
225 
226 
227 enum enum_dyncol_func_result
228 mariadb_dyncol_unpack(DYNAMIC_COLUMN *str,
229                       uint *count,
230                       MYSQL_LEX_STRING **names, DYNAMIC_COLUMN_VALUE **vals);
231 
232 void mariadb_dyncol_unpack_free(MYSQL_LEX_STRING *names,
233                                 DYNAMIC_COLUMN_VALUE *vals);
234 
235 int mariadb_dyncol_column_cmp_named(const MYSQL_LEX_STRING *s1,
236                                     const MYSQL_LEX_STRING *s2);
237 
238 enum enum_dyncol_func_result
239 mariadb_dyncol_column_count(DYNAMIC_COLUMN *str, uint *column_count);
240 
241 #define mariadb_dyncol_value_init(V) (V)->type= DYN_COL_NULL
242 
243 /*
244   Prepare value for using as decimal
245 */
246 void mariadb_dyncol_prepare_decimal(DYNAMIC_COLUMN_VALUE *value);
247 
248 #ifdef __cplusplus
249 }
250 #endif
251 #endif
252