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
));
6 if (!mysql_real_connect(&conn
->db
, host
, user
, pass
, dbname
, 0, NULL
, 0))
7 conn
->msg
= mysql_error(&conn
->db
);
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
);
16 myconn_t
*conn
= NULL
;
17 while (0 == strntok(&str
, &str_len
, CONST_STR_LEN("=;"), &tok
)) {
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
24 if (0 != strntok(&str
, &str_len
, CONST_STR_LEN("=;"), &tok
))
29 myconn_t
*conn
= calloc(1, sizeof(myconn_t
));
31 conn
->msg
= "cannot parse connection string";
33 conn
= maria_connect(host
, dbname
, user
, pass
);
35 if (dbname
) free(dbname
);
41 void maria_disconnect (myconn_t
*conn
) {
42 mysql_close(&conn
->db
);
46 static void maria_reset (myres_t
*res
) {
47 if (res
->res
) mysql_free_result(res
->res
);
48 if (res
->params
) free(res
->params
);
50 for (int i
= 0; i
< res
->nflds
; ++i
)
51 free(res
->result
[i
].buffer
);
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
);
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));
134 res
->msg
= mysql_stmt_error(res
->stmt
);
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
;
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
];
151 bind
->buffer
= (char*)(&fld
->data
);
158 static int set_params (myres_t
*res
, myfld_t
*first
, va_list ap
) {
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
);
171 if (n
< res
->nparams
) {
172 res
->msg
= "not enough parameters for query";
173 rc
= res
->status
= -1;
176 return mysql_stmt_bind_param(res
->stmt
, res
->params
);
179 static int bind_result (myres_t
*res
, int 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
);
198 static void maria_execva (myres_t
*res
, myfld_t
*first
, va_list ap
) {
201 mysql_free_result(res
->res
);
202 res
->res
= mysql_stmt_result_metadata(res
->stmt
);
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));
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
);
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
) {
226 maria_execva(res
, arg
, ap
);
232 int maria_pexec (myres_t
*res
, myfld_t
*arg
, ...) {
235 maria_execva(res
, arg
, ap
);
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
);
243 if (0 == (rc
= res
->status
))
244 rc
= mysql_stmt_execute(res
->stmt
);
245 maria_res_close(res
);
249 int maria_fetch (myres_t
*res
) {
250 res
->status
= mysql_stmt_fetch(res
->stmt
);
251 return res
->status
== MYSQL_NO_DATA
? 0 : 1;