fix
[libdbw.git] / src / mysql / mysql.c
blob651e4e6c08fcbc740243cdb656d8b0a1ecf112ac
1 #include "mysql/mysql.h"
3 myconn_t *maria_connect (const char *host, const char *dbname, const char *user, const char *pass) {
4 myconn_t *conn = calloc(1, sizeof(myconn_t));
5 mysql_init(&conn->db);
6 if (!mysql_real_connect(&conn->db, host, user, pass, dbname, 0, NULL, 0))
7 conn->msg = mysql_error(&conn->db);
8 return conn;
11 myconn_t *maria_connect_str (const char *conn_info) {
12 char *str = (char*)conn_info, *host = NULL, *dbname = NULL, *user = NULL, *pass = NULL;
13 size_t str_len = strlen(str);
14 strptr_t tok;
15 int is_error = 0;
16 myconn_t *conn = NULL;
17 while (0 == strntok(&str, &str_len, CONST_STR_LEN("=;"), &tok)) {
18 is_error = 1;
19 if (0 == cmpcasestr(tok.ptr, tok.len, CONST_STR_LEN("HOST"))) host = strndup(tok.ptr, tok.len); else
20 if (0 == cmpcasestr(tok.ptr, tok.len, CONST_STR_LEN("DBNAME"))) dbname = strndup(tok.ptr, tok.len); else
21 if (0 == cmpcasestr(tok.ptr, tok.len, CONST_STR_LEN("USER"))) user = strndup(tok.ptr, tok.len); else
22 if (0 == cmpcasestr(tok.ptr, tok.len, CONST_STR_LEN("PASS"))) pass = strndup(tok.ptr, tok.len); else
23 break;
24 if (0 != strntok(&str, &str_len, CONST_STR_LEN("=;"), &tok))
25 break;
26 is_error = 0;
28 if (is_error) {
29 myconn_t *conn = calloc(1, sizeof(myconn_t));
30 conn->status = -1;
31 conn->msg = "cannot parse connection string";
32 } else
33 conn = maria_connect(host, dbname, user, pass);
34 if (host) free(host);
35 if (dbname) free(dbname);
36 if (user) free(user);
37 if (pass) free(pass);
38 return conn;
41 void maria_disconnect (myconn_t *conn) {
42 mysql_close(&conn->db);
43 free(conn);
46 static void maria_reset (myres_t *res) {
47 if (res->res) mysql_free_result(res->res);
48 if (res->params) free(res->params);
49 if (res->result) {
50 for (int i = 0; i < res->nflds; ++i)
51 free(res->result[i].buffer);
52 free(res->result);
54 if (res->param_nulls) free(res->param_nulls);
55 if (res->nulls) free(res->nulls);
56 if (res->errors) free(res->errors);
57 if (res->lengths) free(res->lengths);
58 if (res->param_lengths) free(res->param_lengths);
61 void maria_res_close (myres_t *res) {
62 if (res->stmt) mysql_stmt_close(res->stmt);
63 maria_reset(res);
64 free(res);
67 void maria_get_tiny (myres_t *res, int col, myfld_t *fld) {
68 MYSQL_BIND *bind = &res->result[col];
69 fld->type = bind->buffer_type;
70 fld->is_null = *(bind->is_null);
71 fld->data.i1 = *((int8_t*)bind->buffer);
74 void maria_get_smallint (myres_t *res, int col, myfld_t *fld) {
75 MYSQL_BIND *bind = &res->result[col];
76 fld->type = bind->buffer_type;
77 fld->is_null = *(bind->is_null);
78 fld->data.i2 = *((int16_t*)bind->buffer);
81 void maria_get_int (myres_t *res, int col, myfld_t *fld) {
82 MYSQL_BIND *bind = &res->result[col];
83 fld->type = bind->buffer_type;
84 fld->is_null = *(bind->is_null);
85 fld->data.i4 = *((int32_t*)bind->buffer);
88 void maria_get_bigint (myres_t *res, int col, myfld_t *fld) {
89 MYSQL_BIND *bind = &res->result[col];
90 fld->type = bind->buffer_type;
91 fld->is_null = *(bind->is_null);
92 fld->data.i8 = *((int64_t*)bind->buffer);
95 void maria_get_float (myres_t *res, int col, myfld_t *fld) {
96 MYSQL_BIND *bind = &res->result[col];
97 fld->type = bind->buffer_type;
98 fld->is_null = *(bind->is_null);
99 fld->data.f4 = *((float*)bind->buffer);
102 void maria_get_double (myres_t *res, int col, myfld_t *fld) {
103 MYSQL_BIND *bind = &res->result[col];
104 fld->type = bind->buffer_type;
105 fld->is_null = *(bind->is_null);
106 fld->data.f8 = *((double*)bind->buffer);
109 void maria_get_varchar (myres_t *res, int col, myfld_t *fld) {
110 MYSQL_BIND *bind = &res->result[col];
111 fld->type = bind->buffer_type;
112 fld->is_null = *(bind->is_null);
113 fld->data.s.ptr = bind->buffer;
114 fld->data.s.len = *bind->length;
117 myres_t *maria_prepare (myconn_t *conn, const char *sql, size_t sql_len) {
118 myres_t *res = calloc(1, sizeof(myres_t));
119 res->stmt = mysql_stmt_init(&conn->db);
120 if (0 == (res->status = mysql_stmt_prepare(res->stmt, sql, sql_len > 0 ? sql_len : strlen(sql)))) {
121 if (0 < (res->nparams = mysql_stmt_param_count(res->stmt))) {
122 res->params = calloc(res->nparams, sizeof(MYSQL_BIND));
123 res->param_nulls = calloc(res->nparams, sizeof(my_bool));
124 res->param_lengths = calloc(res->nparams, sizeof(unsigned long));
126 // if ((res->res = mysql_stmt_result_metadata(res->stmt))) {
127 // res->nflds = mysql_num_fields(res->res);
128 // res->result = malloc(res->nflds * sizeof(MYSQL_BIND));
129 // res->nulls = malloc(res->nflds * sizeof(my_bool));
130 // res->errors = malloc(res->nflds * sizeof(my_bool));
131 // res->lengths = malloc(res->nflds * sizeof(unsigned long));
132 // }
133 } else
134 res->msg = mysql_stmt_error(res->stmt);
135 return res;
138 static int set_param (myres_t *res, int index, myfld_t *fld) {
139 MYSQL_BIND *bind = &res->params[index];
140 bind->is_null = &res->param_nulls[index];
141 if (0 == (res->param_nulls[index] = fld->is_null)) {
142 bind->buffer_type = fld->type;
143 switch (fld->type) {
144 case MYSQL_TYPE_STRING:
145 case MYSQL_TYPE_VAR_STRING:
146 bind->buffer = fld->data.s.ptr;
147 bind->buffer_length = res->param_lengths[index] = fld->data.s.len;
148 bind->length = &res->param_lengths[index];
149 break;
150 default:
151 bind->buffer = (char*)(&fld->data);
152 break;
155 return 0;
158 static int set_params (myres_t *res, myfld_t *first, va_list ap) {
159 int rc = 0;
160 myfld_t *fld;
161 size_t n = 0;
162 if (first) {
163 memset(res->param_nulls, 0, res->nparams * sizeof(my_bool));
164 set_param(res, n++, first);
165 while (n < res->nparams && (fld = va_arg(ap, myfld_t*)))
166 if (0 != (rc = set_param(res, n++, fld))) {
167 res->msg = mysql_stmt_error(res->stmt);
168 return rc;
171 if (n < res->nparams) {
172 res->msg = "not enough parameters for query";
173 rc = res->status = -1;
175 //return rc;
176 return mysql_stmt_bind_param(res->stmt, res->params);
179 static int bind_result (myres_t *res, int is_reuse) {
180 if (!is_reuse)
181 for (int i = 0; i < res->nflds; ++i) {
182 MYSQL_FIELD *fld = mysql_fetch_field(res->res);
183 MYSQL_BIND *col = &res->result[i];
184 col->buffer_type = fld->type;
185 col->buffer_length = fld->length;
186 col->buffer = malloc(col->buffer_length + 4);
187 col->is_null = &res->nulls[i];
188 col->length = &res->lengths[i];
189 col->error = &res->errors[i];
191 if (0 == (res->status = mysql_stmt_bind_result(res->stmt, res->result)))
192 res->status = mysql_stmt_store_result(res->stmt);
193 if (0 != res->status)
194 res->msg = mysql_stmt_error(res->stmt);
195 return res->status;
198 static void maria_execva (myres_t *res, myfld_t *first, va_list ap) {
199 int is_reuse = 0;
200 if (res->res) {
201 mysql_free_result(res->res);
202 res->res = mysql_stmt_result_metadata(res->stmt);
203 is_reuse = 1;
204 } else
205 if ((res->res = mysql_stmt_result_metadata(res->stmt))) {
206 res->nflds = mysql_num_fields(res->res);
207 res->result = malloc(res->nflds * sizeof(MYSQL_BIND));
208 res->nulls = malloc(res->nflds * sizeof(my_bool));
209 res->errors = malloc(res->nflds * sizeof(my_bool));
210 res->lengths = malloc(res->nflds * sizeof(unsigned long));
212 if (res->res) {
213 if (0 == (res->status = set_params(res, first, ap)) && 0 == (res->status = mysql_stmt_execute(res->stmt)))
214 res->status = bind_result(res, is_reuse);
215 } else
216 res->status = mysql_stmt_execute(res->stmt);
217 if (0 != res->status && !res->msg)
218 res->msg = mysql_stmt_error(res->stmt);
221 myres_t *maria_exec (myconn_t *conn, const char *sql, size_t sql_len, myfld_t *arg, ...) {
222 myres_t *res = maria_prepare(conn, sql, sql_len);
223 if (0 == res->status) {
224 va_list ap;
225 va_start(ap, arg);
226 maria_execva(res, arg, ap);
227 va_end(ap);
229 return res;
232 int maria_pexec (myres_t *res, myfld_t *arg, ...) {
233 va_list ap;
234 va_start(ap, arg);
235 maria_execva(res, arg, ap);
236 va_end(ap);
237 return res->status;
240 int maria_exec_sql (myconn_t *conn, const char *sql, size_t sql_len) {
241 myres_t *res = maria_prepare(conn, sql, sql_len);
242 int rc;
243 if (0 == (rc = res->status))
244 rc = mysql_stmt_execute(res->stmt);
245 maria_res_close(res);
246 return rc;
249 int maria_fetch (myres_t *res) {
250 res->status = mysql_stmt_fetch(res->stmt);
251 return res->status == MYSQL_NO_DATA ? 0 : 1;