59 * anymore, and should be set to NULL. |
72 * anymore, and should be set to NULL. |
60 */ |
73 */ |
61 static int _evsql_query_exec (struct evsql *evsql, struct evsql_query *query, const char *command) { |
74 static int _evsql_query_exec (struct evsql *evsql, struct evsql_query *query, const char *command) { |
62 switch (evsql->type) { |
75 switch (evsql->type) { |
63 case EVSQL_EVPQ: |
76 case EVSQL_EVPQ: |
64 // just pass it through |
77 // got params? |
65 return evpq_query(evsql->engine.evpq, command); |
78 if (query->params.count) { |
|
79 return evpq_query_params(evsql->engine.evpq, command, |
|
80 query->params.count, |
|
81 query->params.types, |
|
82 query->params.values, |
|
83 query->params.lengths, |
|
84 query->params.formats, |
|
85 query->params.result_format |
|
86 ); |
|
87 |
|
88 } else { |
|
89 // plain 'ole query |
|
90 return evpq_query(evsql->engine.evpq, command); |
|
91 } |
66 |
92 |
67 default: |
93 default: |
68 FATAL("evsql->type"); |
94 FATAL("evsql->type"); |
69 } |
95 } |
70 } |
96 } |
71 |
97 |
72 /* |
98 /* |
|
99 * Free the query and related resources, doesn't trigger any callbacks or remove from any queues |
|
100 */ |
|
101 static void _evsql_query_free (struct evsql_query *query) { |
|
102 assert(query->command == NULL); |
|
103 |
|
104 // free params if present |
|
105 free(query->params.types); |
|
106 free(query->params.values); |
|
107 free(query->params.lengths); |
|
108 free(query->params.formats); |
|
109 |
|
110 // free the query itself |
|
111 free(query); |
|
112 } |
|
113 |
|
114 /* |
73 * Dequeue the query, execute the callback, and free it. |
115 * Dequeue the query, execute the callback, and free it. |
74 */ |
116 */ |
75 static void _evsql_query_done (struct evsql_query *query, const struct evsql_result_info *result_info) { |
117 static void _evsql_query_done (struct evsql_query *query, const struct evsql_result_info *result_info) { |
76 assert(query->command == NULL); |
|
77 |
118 |
78 // dequeue |
119 // dequeue |
79 TAILQ_REMOVE(&query->evsql->queue, query, entry); |
120 TAILQ_REMOVE(&query->evsql->queue, query, entry); |
80 |
121 |
81 if (result_info) |
122 if (result_info) |
82 // call the callback |
123 // call the callback |
83 query->cb_fn(*result_info, query->cb_arg); |
124 query->cb_fn(*result_info, query->cb_arg); |
84 |
125 |
85 // free |
126 // free |
86 free(query); |
127 _evsql_query_free(query); |
87 } |
128 } |
88 |
129 |
89 /* |
130 /* |
90 * A query has failed, notify the user and remove it. |
131 * A query has failed, notify the user and remove it. |
91 */ |
132 */ |
296 default: |
337 default: |
297 FATAL("evsql->type"); |
338 FATAL("evsql->type"); |
298 } |
339 } |
299 } |
340 } |
300 |
341 |
301 |
342 static struct evsql_query *_evsql_query_new (struct evsql *evsql, evsql_query_cb query_fn, void *cb_arg) { |
302 struct evsql_query *evsql_query (struct evsql *evsql, const char *command, evsql_query_cb query_fn, void *cb_arg) { |
|
303 struct evsql_query *query; |
343 struct evsql_query *query; |
304 int idle; |
344 |
305 |
|
306 // allocate it |
345 // allocate it |
307 if ((query = calloc(1, sizeof(*query))) == NULL) |
346 if ((query = calloc(1, sizeof(*query))) == NULL) |
308 ERROR("calloc"); |
347 ERROR("calloc"); |
309 |
348 |
310 // store |
349 // store |
311 query->evsql = evsql; |
350 query->evsql = evsql; |
312 query->cb_fn = query_fn; |
351 query->cb_fn = query_fn; |
313 query->cb_arg = cb_arg; |
352 query->cb_arg = cb_arg; |
|
353 |
|
354 // success |
|
355 return query; |
|
356 |
|
357 error: |
|
358 return NULL; |
|
359 } |
|
360 |
|
361 static int _evsql_query_enqueue (struct evsql *evsql, struct evsql_query *query, const char *command) { |
|
362 int idle; |
314 |
363 |
315 // check state |
364 // check state |
316 if ((idle = _evsql_query_idle(evsql)) < 0) |
365 if ((idle = _evsql_query_idle(evsql)) < 0) |
317 ERROR("connection is not valid"); |
366 ERROR("connection is not valid"); |
318 |
367 |
329 ERROR("strdup"); |
378 ERROR("strdup"); |
330 } |
379 } |
331 |
380 |
332 // store it on the list |
381 // store it on the list |
333 TAILQ_INSERT_TAIL(&evsql->queue, query, entry); |
382 TAILQ_INSERT_TAIL(&evsql->queue, query, entry); |
334 |
383 |
335 // success |
384 // ok, good |
|
385 return 0; |
|
386 |
|
387 error: |
|
388 return -1; |
|
389 } |
|
390 |
|
391 struct evsql_query *evsql_query (struct evsql *evsql, const char *command, evsql_query_cb query_fn, void *cb_arg) { |
|
392 struct evsql_query *query = NULL; |
|
393 |
|
394 // alloc new query |
|
395 if ((query = _evsql_query_new(evsql, query_fn, cb_arg)) == NULL) |
|
396 goto error; |
|
397 |
|
398 // just execute the command string directly |
|
399 if (_evsql_query_enqueue(evsql, query, command)) |
|
400 goto error; |
|
401 |
|
402 // ok |
336 return query; |
403 return query; |
337 |
404 |
338 error: |
405 error: |
339 // do *NOT* free query->command, ever |
406 _evsql_query_free(query); |
340 free(query); |
|
341 |
407 |
342 return NULL; |
408 return NULL; |
343 } |
409 } |
344 |
410 |
|
411 struct evsql_query *evsql_query_params (struct evsql *evsql, const char *command, struct evsql_query_params params, evsql_query_cb query_fn, void *cb_arg) { |
|
412 struct evsql_query *query = NULL; |
|
413 struct evsql_query_param *param; |
|
414 int idx; |
|
415 |
|
416 // alloc new query |
|
417 if ((query = _evsql_query_new(evsql, query_fn, cb_arg)) == NULL) |
|
418 goto error; |
|
419 |
|
420 // count the params |
|
421 for (param = params.list; param->value || param->length; param++) |
|
422 query->params.count++; |
|
423 |
|
424 // allocate the vertical storage for the parameters |
|
425 if (0 |
|
426 |
|
427 // !(query->params.types = calloc(query->params.count, sizeof(Oid))) |
|
428 || !(query->params.values = calloc(query->params.count, sizeof(char *))) |
|
429 || !(query->params.lengths = calloc(query->params.count, sizeof(int))) |
|
430 || !(query->params.formats = calloc(query->params.count, sizeof(int))) |
|
431 ) |
|
432 ERROR("calloc"); |
|
433 |
|
434 // transform |
|
435 for (param = params.list, idx = 0; param->value || param->length; param++, idx++) { |
|
436 // `types` stays NULL |
|
437 // query->params.types[idx] = 0; |
|
438 |
|
439 // values |
|
440 query->params.values[idx] = param->value; |
|
441 |
|
442 // lengths (nonzero for NULLs) |
|
443 query->params.lengths[idx] = param->value ? param->length : 0; |
|
444 |
|
445 // formats, binary if length is nonzero |
|
446 query->params.formats[idx] = param->value && param->length; |
|
447 } |
|
448 |
|
449 // result format |
|
450 query->params.result_format = params.result_binary ? 1 : 0; |
|
451 |
|
452 // execute it |
|
453 if (_evsql_query_enqueue(evsql, query, command)) |
|
454 goto error; |
|
455 |
|
456 // ok |
|
457 return query; |
|
458 |
|
459 error: |
|
460 _evsql_query_free(query); |
|
461 |
|
462 return NULL; |
|
463 } |
|
464 |