Patterns in static

Apophenia

Loading...
Searching...
No Matches
apop_db_mysql.c
1
3
4/* Copyright (c) 2006--2007 by Ben Klemens. Licensed under the GPLv2; see COPYING. */
5
6#include <mysql.h>
7#include <math.h>
8
9static MYSQL *mysql_db;
10
11#define Areweconected(retval) Apop_stopif(!mysql_db, return retval, 0, \
12 "No connection to a mySQL/mariadb database. apop_db_open() failure?");
13
14static char *opt_host_name = NULL; /* server host (default=localhost) */
15static unsigned int opt_port_num = 0; /* port number (use built-in value) */
16static char *opt_socket_name = NULL; /* socket name (use built-in value) */
17static unsigned int opt_flags = 0; /* connection flags (none) */
18
19#define Apop_mstopif(cond, returnop, str) \
20 Apop_stopif(cond, returnop, 0, \
21 str "\n mySQL/mariadb error %u: %s\n", mysql_errno (mysql_db), mysql_error (mysql_db));
22
23static int apop_mysql_db_open(char const *in){
24 Apop_stopif(!in, return 2, 0, "MySQL needs a non-NULL db name.");
25 mysql_db = mysql_init (NULL);
26 Apop_stopif(!mysql_db, return 1, 0, "mysql_init() failed (probably out of memory)");
27 Apop_mstopif (!mysql_real_connect (mysql_db, opt_host_name, apop_opts.db_user, apop_opts.db_pass,
28 in, opt_port_num, opt_socket_name, CLIENT_MULTI_STATEMENTS+opt_flags),
29 mysql_close (mysql_db); return 1,
30 "mysql_real_connect() failed");
31 return 0;
32}
33
34static void apop_mysql_db_close(int ignoreme){
35 if (mysql_db) mysql_close (mysql_db);
36}
37
38/*
39 //Cut & pasted & cleaned from the mysql manual.
40static void process_results(void){
41 else // mysql_store_result() returned nothing; should it have?
42 Apop_stopif(mysql_field_count(mysql_db) == 0, , 0, "apop_query error");
43 //else query wasn't a select & just didn't return data.
44}
45 */
46
47static double apop_mysql_query(char *query){
48 Apop_mstopif(mysql_query(mysql_db, query), return 1, "apop_mysql_query failed");
49 MYSQL_RES *result = mysql_store_result(mysql_db);
50 if (result) mysql_free_result(result);
51 return 0;
52}
53
54static double apop_mysql_table_exists(char const *table, int delme){
55 Areweconected(GSL_NAN);
56 MYSQL_RES *res_set = mysql_list_tables(mysql_db, table);
57 Apop_mstopif(!mysql_list_tables(mysql_db, table), return GSL_NAN,
58 "show tables query failed.");
59 int is_found = mysql_num_rows(res_set);
60 mysql_free_result(res_set);
61 if (!is_found) return 0;
62
63 if (delme =='d' || delme=='D'){
64 char *a_query;
65 Asprintf(&a_query, "drop table %s", table);
66 Apop_mstopif(mysql_query (mysql_db, a_query), GSL_NAN,
67 "table exists, but table dropping failed");
68 }
69 return 1;
70}
71
72#define check_and_clean(do_if_failure) \
73 Apop_mstopif( mysql_errno (conn), \
74 if (out) do_if_failure; return NULL, \
75 "mysql_fetch_row() failed"); \
76 return out; \
77
78static int get_name_row(unsigned int *num_fields, MYSQL_FIELD *fields){
79 for(size_t i = 0; i < *num_fields; i++)
80 if (apop_opts.db_name_column && !strcasecmp(fields[i].name, apop_opts.db_name_column)){
81 (*num_fields)--;
82 return i;
83 }
84 return -1;
85}
86
87static void * process_result_set_data (MYSQL *conn, MYSQL_RES *res_set) {
88 MYSQL_ROW row;
89 unsigned int num_fields = mysql_num_fields(res_set);
90 unsigned int num_rows = mysql_num_rows (res_set);
91 if (!num_fields || !num_rows) return NULL;
92
93 MYSQL_FIELD *fields = mysql_fetch_fields(res_set);
94 int name_row = get_name_row(&num_fields, fields);
95
96 apop_data *out = apop_data_alloc(0, num_rows, num_fields);
97
98 for(size_t i = 0; i < num_fields+ (name_row>=0); i++)
99 if (i!=name_row) apop_name_add(out->names, fields[i].name, 'c');
100
101 for (int i=0; (row = mysql_fetch_row (res_set)); i++) {
102 int passed_name = 0;
103 for (size_t j = 0; j < mysql_num_fields (res_set); j++){
104 if (j==name_row){
105 apop_name_add(out->names, row[j], 'r');
106 passed_name = 1;
107 continue;
108 }
109 if (!row[j]) apop_data_set(out, i , j-passed_name, NAN);
110 else {
111 char *end = NULL;
112 double num = strtod(row[j], &end);
113 apop_data_set(out, i , j-passed_name, *end ? NAN : num);
114 }
115 }
116 }
117 check_and_clean(apop_data_free(out))
118}
119
120static void * process_result_set_vector (MYSQL *conn, MYSQL_RES *res_set) {
121 MYSQL_ROW row;
122 unsigned int num_fields = mysql_num_fields(res_set);
123 unsigned int num_rows = mysql_num_rows (res_set);
124 if (num_fields == 0 || num_rows == 0) return NULL;
125 gsl_vector *out = gsl_vector_alloc(num_rows);
126 for (int j=0; (row = mysql_fetch_row (res_set)); j++){
127 double valor = (!row[0] || !strcmp(row[0], "NULL"))
128 ? GSL_NAN : atof(row[0]);
129 gsl_vector_set(out, j, valor);
130 }
131 check_and_clean(gsl_vector_free(out))
132}
133
134static void * process_result_set_chars (MYSQL *conn, MYSQL_RES *res_set) {
135 MYSQL_ROW row;
136 unsigned int total_cols = mysql_num_fields(res_set);
137 unsigned int total_rows = mysql_num_rows(res_set);
138
139 MYSQL_FIELD *fields = mysql_fetch_fields(res_set);
140 int name_row = get_name_row(&total_cols, fields);
141 apop_data *out = apop_text_alloc(NULL, total_rows, total_cols);
142
143 for (size_t i = 0; i < total_cols + (name_row>=0); i++)
144 if (i!=name_row) apop_name_add(out->names, fields[i].name, 't');
145
146 for (int i=0; (row = mysql_fetch_row (res_set)); i++){
147 int passed_name = 0;
148 for (size_t jj=0; jj<total_cols; jj++){
149 if (jj==name_row){
150 apop_name_add(out->names, row[jj], 'r');
151 passed_name = 1;
152 continue;
153 }
154 apop_text_set(out, i, jj-passed_name, "%s", (row[jj]==NULL)? apop_opts.nan_string : row[jj]);
155 }
156 }
157 check_and_clean(;)
158}
159
160static void * apop_mysql_query_core(char *query, void *(*callback)(MYSQL*, MYSQL_RES*)){
161 Areweconected(NULL);
162 apop_data *output = NULL;
163 Apop_mstopif(mysql_query (mysql_db, query), return NULL, "mysql_query() failed");
164 MYSQL_RES *res_set = mysql_store_result (mysql_db);
165 Apop_mstopif(!res_set,
166 if (callback == process_result_set_data || callback==process_result_set_data) apop_return_data_error('q')
167 else return NULL,
168 "mysql_store_result() failed");
169 if (!res_set->row_count) goto done; //just a blank table.
170 output = callback(mysql_db, res_set);
171
172 done:
173 mysql_free_result (res_set);
174 return output;
175}
176
177static double apop_mysql_query_to_float(char *query){
178 Areweconected(GSL_NAN);
179 Apop_mstopif(mysql_query (mysql_db, query) != 0, return GSL_NAN,
180 "mysql_query() failed");
181 MYSQL_RES *res_set = mysql_store_result (mysql_db);
182 Apop_mstopif(!res_set, return GSL_NAN, "mysql_store_result() failed");
183 if (mysql_num_rows(res_set)==0) return GSL_NAN;
184 MYSQL_ROW row = mysql_fetch_row (res_set);
185 Apop_mstopif(mysql_errno (mysql_db),
186 mysql_free_result (res_set); return GSL_NAN,
187 "mysql_fetch_row() failed");
188 double out = atof(row[0]);
189 mysql_free_result (res_set);
190 return out;
191}
192
193apop_data* apop_mysql_mixed_query(char const *intypes, char const *query){
194 Areweconected(NULL);
195 apop_data *out = NULL;
196 Apop_mstopif(mysql_query (mysql_db, query), return NULL, "mysql_query() failed");
197 MYSQL_RES *res_set = mysql_store_result(mysql_db);
198 MYSQL_ROW row;
199 Apop_mstopif(!res_set, return NULL, "mysql_store_result() failed");
200 if (!res_set->row_count) goto done; //just a blank table.
201
202 unsigned int total_cols = mysql_num_fields(res_set);
203 unsigned int total_rows = mysql_num_rows(res_set);
204 if (!total_cols || !total_rows) goto done;
205
206 apop_qt info = { };
207 count_types(&info, intypes); //in apop_db_sqlite.c
208 //intypes[5] === names, vectors, mcols, textcols, weights.
209
210 out = apop_data_alloc(info.intypes[1] ? total_rows : 0,
211 info.intypes[2] ? total_rows : 0,
212 info.intypes[2]);
213
214 int requested = info.intypes[0]+info.intypes[1]+info.intypes[2]+info.intypes[3]+info.intypes[4];
215 int excess = requested - total_cols;
216 Apop_stopif(excess > 0, out->error='d' /*and continue.*/, 1,
217 "you asked for %i columns in your list of types(%s), but your query produced %u columns. "
218 "The remainder will be placed in the text section. Output data set's ->error element set to 'd'." , requested, intypes, total_cols);
219 Apop_stopif(excess < 0, out->error='d' /*and continue.*/, 1,
220 "you asked for %i columns in your list of types(%s), but your query produced %u columns. "
221 "Ignoring the last %i type(s) in your list. Output data set's ->error element set to 'd'." , requested, intypes, total_cols, -excess);
222
223 if (info.intypes[3]||excess>0) apop_text_alloc(out, total_rows, info.intypes[3] + ((excess > 0) ? excess : 0));
224 if (info.intypes[4]) out->weights = gsl_vector_alloc(total_rows);
225
226 MYSQL_FIELD *fields = mysql_fetch_fields(res_set);
227 for (size_t i=0; i<total_cols; i++){
228 char c = (i < requested) ? intypes[i] : 't';
229 if (c == 't'|| c=='T')
230 apop_name_add(out->names, fields[i].name, 't');
231 else if (c == 'v'|| c=='V')
232 apop_name_add(out->names, fields[i].name, 'v');
233 else if (c == 'm'|| c=='M')
234 apop_name_add(out->names, fields[i].name, 'c');
235 }
236
237 for (int i=0; (row = mysql_fetch_row (res_set)); i++) {
238 int thism=0, thist=0;
239 for (size_t j=0; j<total_cols; j++){
240 char c = (j < requested) ? intypes[j] : 't';
241 if (c == 'n' || c =='N')
242 apop_name_add(out->names, row[j], 'r');
243 else if (c == 't'|| c=='T')
244 apop_text_set(out, i, thist++, "%s", (row[j]==NULL)? apop_opts.nan_string : row[j]);
245 else if (c == 'v'|| c=='V'){
246 double valor = (!row[j] || !strcmp(row[j], "NULL")) ? NAN : atof(row[j]);
247 gsl_vector_set(out->vector, i, valor);
248 } else if (c == 'w'|| c=='W'){
249 double valor = (!row[j] || !strcmp(row[j], "NULL")) ? NAN : atof(row[j]);
250 gsl_vector_set(out->weights, i, valor);
251 } else if (c == 'm'|| c=='M')
252 gsl_matrix_set(out->matrix, i , thism++, row[j] ? atof(row[j]): GSL_NAN);
253 }
254 }
255
256 done:
257 mysql_free_result (res_set);
258 return out;
259}
#define apop_data_free(freeme)
Definition docs/include/apop.h:192
int apop_data_set(apop_data *data, size_t row, int col, const double val, const char *rowname, const char *colname, const char *page)
Definition apop_data.c:915
apop_data * apop_text_alloc(apop_data *in, const size_t row, const size_t col)
Definition apop_data.c:1063
#define Apop_stopif(test, onfail, level,...)
Definition docs/include/apop.h:1030
apop_data * apop_data_alloc(const size_t size1, const size_t size2, const int size3)
Definition apop_data.c:34
int apop_name_add(apop_name *n, char const *add_me, char type)
Definition apop_name.c:42
int apop_text_set(apop_data *in, const size_t row, const size_t col, const char *fmt,...)
Definition apop_data.c:1035
Definition docs/include/apop.h:72
Autogenerated by doxygen (Debian ).