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 
32 #ifdef	__cplusplus
33 extern "C" {
34 #endif
35 
36 #ifndef LIBMARIADB
37 #include <decimal.h>
38 #include <my_decimal_limits.h>
39 #endif
40 #include <mysql.h>
41 
42 #ifndef longlong_defined
43 #if defined(HAVE_LONG_LONG) && SIZEOF_LONG != 8
44 typedef unsigned long long int ulonglong; /* ulong or unsigned long long */
45 typedef long long int longlong;
46 #else
47 typedef unsigned long	ulonglong;	/* ulong or unsigned long long */
48 typedef long		longlong;
49 #endif
50 #define longlong_defined
51 #endif
52 
53 
54 #ifndef _my_sys_h
55 typedef struct st_dynamic_string
56 {
57   char *str;
58   size_t length,max_length,alloc_increment;
59 } DYNAMIC_STRING;
60 #endif
61 
62 struct st_mysql_lex_string
63 {
64   char *str;
65   size_t length;
66 };
67 typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
68 typedef struct st_mysql_lex_string LEX_STRING;
69 /*
70   Limits of implementation
71 */
72 #define MAX_TOTAL_NAME_LENGTH 65535
73 #define MAX_NAME_LENGTH (MAX_TOTAL_NAME_LENGTH/4)
74 
75 /* NO and OK is the same used just to show semantics */
76 #define ER_DYNCOL_NO ER_DYNCOL_OK
77 
78 enum enum_dyncol_func_result
79 {
80   ER_DYNCOL_OK= 0,
81   ER_DYNCOL_YES= 1,                /* For functions returning 0/1 */
82   ER_DYNCOL_FORMAT= -1,            /* Wrong format of the encoded string */
83   ER_DYNCOL_LIMIT=  -2,            /* Some limit reached */
84   ER_DYNCOL_RESOURCE= -3,          /* Out of resourses */
85   ER_DYNCOL_DATA= -4,              /* Incorrect input data */
86   ER_DYNCOL_UNKNOWN_CHARSET= -5,   /* Unknown character set */
87   ER_DYNCOL_TRUNCATED= 2           /* OK, but data was truncated */
88 };
89 
90 typedef DYNAMIC_STRING DYNAMIC_COLUMN;
91 
92 enum enum_dynamic_column_type
93 {
94   DYN_COL_NULL= 0,
95   DYN_COL_INT,
96   DYN_COL_UINT,
97   DYN_COL_DOUBLE,
98   DYN_COL_STRING,
99   DYN_COL_DECIMAL,
100   DYN_COL_DATETIME,
101   DYN_COL_DATE,
102   DYN_COL_TIME,
103   DYN_COL_DYNCOL
104 };
105 
106 typedef enum enum_dynamic_column_type DYNAMIC_COLUMN_TYPE;
107 
108 struct st_dynamic_column_value
109 {
110   DYNAMIC_COLUMN_TYPE type;
111   union
112   {
113     long long long_value;
114     unsigned long long ulong_value;
115     double double_value;
116     struct {
117       MYSQL_LEX_STRING value;
118       MARIADB_CHARSET_INFO *charset;
119     } string;
120 #ifndef LIBMARIADB
121     struct {
122       decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
123       decimal_t value;
124     } decimal;
125 #endif
126     MYSQL_TIME time_value;
127   } x;
128 };
129 
130 typedef struct st_dynamic_column_value DYNAMIC_COLUMN_VALUE;
131 
132 #ifdef MADYNCOL_DEPRECATED
133 enum enum_dyncol_func_result
134 dynamic_column_create(DYNAMIC_COLUMN *str,
135                       uint column_nr, DYNAMIC_COLUMN_VALUE *value);
136 
137 enum enum_dyncol_func_result
138 dynamic_column_create_many(DYNAMIC_COLUMN *str,
139                            uint column_count,
140                            uint *column_numbers,
141                            DYNAMIC_COLUMN_VALUE *values);
142 enum enum_dyncol_func_result
143 dynamic_column_update(DYNAMIC_COLUMN *org, uint column_nr,
144                       DYNAMIC_COLUMN_VALUE *value);
145 enum enum_dyncol_func_result
146 dynamic_column_update_many(DYNAMIC_COLUMN *str,
147                            uint add_column_count,
148                            uint *column_numbers,
149                            DYNAMIC_COLUMN_VALUE *values);
150 
151 enum enum_dyncol_func_result
152 dynamic_column_exists(DYNAMIC_COLUMN *org, uint column_nr);
153 
154 enum enum_dyncol_func_result
155 dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint);
156 
157 enum enum_dyncol_func_result
158 dynamic_column_get(DYNAMIC_COLUMN *org, uint column_nr,
159                    DYNAMIC_COLUMN_VALUE *store_it_here);
160 #endif
161 
162 /* new functions */
163 enum enum_dyncol_func_result
164 mariadb_dyncol_create_many_num(DYNAMIC_COLUMN *str,
165                                uint column_count,
166                                uint *column_numbers,
167                                DYNAMIC_COLUMN_VALUE *values,
168                                my_bool new_string);
169 enum enum_dyncol_func_result
170 mariadb_dyncol_create_many_named(DYNAMIC_COLUMN *str,
171                                  uint column_count,
172                                  MYSQL_LEX_STRING *column_keys,
173                                  DYNAMIC_COLUMN_VALUE *values,
174                                  my_bool new_string);
175 
176 
177 enum enum_dyncol_func_result
178 mariadb_dyncol_update_many_num(DYNAMIC_COLUMN *str,
179                                uint add_column_count,
180                                uint *column_keys,
181                                DYNAMIC_COLUMN_VALUE *values);
182 enum enum_dyncol_func_result
183 mariadb_dyncol_update_many_named(DYNAMIC_COLUMN *str,
184                                  uint add_column_count,
185                                  MYSQL_LEX_STRING *column_keys,
186                                  DYNAMIC_COLUMN_VALUE *values);
187 
188 
189 enum enum_dyncol_func_result
190 mariadb_dyncol_exists_num(DYNAMIC_COLUMN *org, uint column_nr);
191 enum enum_dyncol_func_result
192 mariadb_dyncol_exists_named(DYNAMIC_COLUMN *str, MYSQL_LEX_STRING *name);
193 
194 /* List of not NULL columns */
195 enum enum_dyncol_func_result
196 mariadb_dyncol_list_num(DYNAMIC_COLUMN *str, uint *count, uint **nums);
197 enum enum_dyncol_func_result
198 mariadb_dyncol_list_named(DYNAMIC_COLUMN *str, uint *count,
199                           MYSQL_LEX_STRING **names);
200 
201 /*
202    if the column do not exists it is NULL
203 */
204 enum enum_dyncol_func_result
205 mariadb_dyncol_get_num(DYNAMIC_COLUMN *org, uint column_nr,
206                        DYNAMIC_COLUMN_VALUE *store_it_here);
207 enum enum_dyncol_func_result
208 mariadb_dyncol_get_named(DYNAMIC_COLUMN *str, MYSQL_LEX_STRING *name,
209                          DYNAMIC_COLUMN_VALUE *store_it_here);
210 
211 my_bool mariadb_dyncol_has_names(DYNAMIC_COLUMN *str);
212 
213 enum enum_dyncol_func_result
214 mariadb_dyncol_check(DYNAMIC_COLUMN *str);
215 
216 enum enum_dyncol_func_result
217 mariadb_dyncol_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json);
218 
219 void mariadb_dyncol_free(DYNAMIC_COLUMN *str);
220 
221 #define mariadb_dyncol_init(A) memset((A), 0, sizeof(DYNAMIC_COLUMN))
222 #define dynamic_column_initialize(A) mariadb_dyncol_init((A))
223 #define dynamic_column_column_free(A) mariadb_dyncol_free((A))
224 
225 /* conversion of values to 3 base types */
226 enum enum_dyncol_func_result
227 mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
228                        MARIADB_CHARSET_INFO *cs, char quote);
229 enum enum_dyncol_func_result
230 mariadb_dyncol_val_long(longlong *ll, DYNAMIC_COLUMN_VALUE *val);
231 enum enum_dyncol_func_result
232 mariadb_dyncol_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val);
233 
234 enum enum_dyncol_func_result
235 mariadb_dyncol_unpack(DYNAMIC_COLUMN *str,
236                       uint *count,
237                       MYSQL_LEX_STRING **names, DYNAMIC_COLUMN_VALUE **vals);
238 
239 int mariadb_dyncol_column_cmp_named(const MYSQL_LEX_STRING *s1,
240                                     const MYSQL_LEX_STRING *s2);
241 
242 enum enum_dyncol_func_result
243 mariadb_dyncol_column_count(DYNAMIC_COLUMN *str, uint *column_count);
244 
245 #define mariadb_dyncol_value_init(V) \
246 do {\
247   (V)->type= DYN_COL_NULL;\
248 } while(0)
249 
250 /*
251   Prepare value for using as decimal
252 */
253 void mariadb_dyncol_prepare_decimal(DYNAMIC_COLUMN_VALUE *value);
254 
255 
256 #ifdef	__cplusplus
257 }
258 #endif
259 #endif
260