trilogy_w_prepared_statements 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +80 -0
  4. data/Rakefile +22 -0
  5. data/ext/trilogy-ruby/cast.c +277 -0
  6. data/ext/trilogy-ruby/cext.c +1048 -0
  7. data/ext/trilogy-ruby/extconf.rb +17 -0
  8. data/ext/trilogy-ruby/inc/trilogy/blocking.h +281 -0
  9. data/ext/trilogy-ruby/inc/trilogy/buffer.h +64 -0
  10. data/ext/trilogy-ruby/inc/trilogy/builder.h +165 -0
  11. data/ext/trilogy-ruby/inc/trilogy/charset.h +277 -0
  12. data/ext/trilogy-ruby/inc/trilogy/client.h +760 -0
  13. data/ext/trilogy-ruby/inc/trilogy/error.h +44 -0
  14. data/ext/trilogy-ruby/inc/trilogy/packet_parser.h +34 -0
  15. data/ext/trilogy-ruby/inc/trilogy/protocol.h +1014 -0
  16. data/ext/trilogy-ruby/inc/trilogy/reader.h +216 -0
  17. data/ext/trilogy-ruby/inc/trilogy/socket.h +111 -0
  18. data/ext/trilogy-ruby/inc/trilogy/vendor/curl_hostcheck.h +29 -0
  19. data/ext/trilogy-ruby/inc/trilogy/vendor/openssl_hostname_validation.h +51 -0
  20. data/ext/trilogy-ruby/inc/trilogy.h +8 -0
  21. data/ext/trilogy-ruby/src/blocking.c +358 -0
  22. data/ext/trilogy-ruby/src/buffer.c +60 -0
  23. data/ext/trilogy-ruby/src/builder.c +236 -0
  24. data/ext/trilogy-ruby/src/charset.c +212 -0
  25. data/ext/trilogy-ruby/src/client.c +903 -0
  26. data/ext/trilogy-ruby/src/error.c +17 -0
  27. data/ext/trilogy-ruby/src/packet_parser.c +140 -0
  28. data/ext/trilogy-ruby/src/protocol.c +1175 -0
  29. data/ext/trilogy-ruby/src/reader.c +282 -0
  30. data/ext/trilogy-ruby/src/socket.c +623 -0
  31. data/ext/trilogy-ruby/src/vendor/curl_hostcheck.c +206 -0
  32. data/ext/trilogy-ruby/src/vendor/openssl_hostname_validation.c +175 -0
  33. data/ext/trilogy-ruby/trilogy-ruby.h +37 -0
  34. data/lib/trilogy/version.rb +3 -0
  35. data/lib/trilogy.rb +61 -0
  36. data/trilogy.gemspec +27 -0
  37. metadata +107 -0
@@ -0,0 +1,760 @@
1
+ #ifndef TRILOGY_CLIENT_H
2
+ #define TRILOGY_CLIENT_H
3
+
4
+ #include <sys/socket.h>
5
+ #include <sys/types.h>
6
+ #include <unistd.h>
7
+
8
+ #include "trilogy/buffer.h"
9
+ #include "trilogy/packet_parser.h"
10
+ #include "trilogy/protocol.h"
11
+ #include "trilogy/socket.h"
12
+
13
+ /* Trilogy Non-blocking Client API
14
+ *
15
+ * This API is designed for allowing the caller to deal with I/O themselves.
16
+ * The API is split into `_send` and `_recv` calls. Allowing the caller to wait
17
+ * on writeability before calling a `_send` function, and waiting for
18
+ * readability before `_recv` calls. This can especially be useful for
19
+ * applications that live inside of managed runtime or event-loop.
20
+ *
21
+ * Some pseudo-code typical lifecycle of a connection might look something like
22
+ * this:
23
+ *
24
+ * trilogy_conn_t conn;
25
+ * trilogy_init(&conn);
26
+ *
27
+ * trilogy_connect_send(&conn, addrinfo);
28
+ *
29
+ * trilogy_handshake_t handshake;
30
+ * trilogy_connect_recv(&conn, &handshake);
31
+ *
32
+ * trilogy_auth_send(&conn, &handshake, "root", NULL, 0, 0);
33
+ * int rc = trilogy_auth_recv(&conn, &handshake);
34
+ * if (rc == TRILOGY_AUTH_SWITCH) {
35
+ * trilogy_auth_switch_send(&conn, &handshake);
36
+ * trilogy_auth_recv(&conn, &handshake);
37
+ * }
38
+ *
39
+ * At this point the connection is open, authenticated, and ready for commands.
40
+ * From here a caller can start issuing commands:
41
+ *
42
+ * char* db_name = "test";
43
+ * trilogy_change_db_send(&conn, db_name, strlen(db_name));
44
+ * trilogy_change_db_recv(&conn);
45
+ *
46
+ * Assuming the connection isn't in an error state, and all responses have been
47
+ * read off the network - it's ready for another command.
48
+ *
49
+ * Specific to the trilogy_query_send/trilogy_query_recv lifecycle - if
50
+ * TRILOGY_HAVE_RESULTS is returned from trilogy_query_recv, the caller *must* read
51
+ * all columns and rows from the server before the connection will be command-
52
+ * ready again. This is a requirement of a MySQL-compatible protocol.
53
+ *
54
+ * trilogy_close_send/trilogy_close_recv may be used to sent a quit command to the
55
+ * server. While this is considered best practice, simply calling trilogy_free
56
+ * to close the socket and free any internal buffers is enough to clean things
57
+ * up.
58
+ */
59
+
60
+ #define TRILOGY_DEFAULT_BUF_SIZE 32768
61
+
62
+ /* trilogy_column_t - The Trilogy client's column type.
63
+ */
64
+ typedef trilogy_column_packet_t trilogy_column_t;
65
+
66
+ /* trilogy_conn_t - The Trilogy client's instance type.
67
+ *
68
+ * This type is shared for the non-blocking and blocking versions of the API.
69
+ */
70
+ typedef struct {
71
+ uint64_t affected_rows;
72
+ uint64_t last_insert_id;
73
+ uint16_t warning_count;
74
+ char last_gtid[TRILOGY_MAX_LAST_GTID_LEN];
75
+ size_t last_gtid_len;
76
+
77
+ uint16_t error_code;
78
+ const char *error_message;
79
+ size_t error_message_len;
80
+
81
+ uint32_t capabilities;
82
+ uint16_t server_status;
83
+
84
+ trilogy_sock_t *socket;
85
+
86
+ // private:
87
+ uint8_t recv_buff[TRILOGY_DEFAULT_BUF_SIZE];
88
+ size_t recv_buff_pos;
89
+ size_t recv_buff_len;
90
+
91
+ trilogy_packet_parser_t packet_parser;
92
+ trilogy_buffer_t packet_buffer;
93
+ size_t packet_buffer_written;
94
+
95
+ uint64_t column_count;
96
+ bool started_reading_rows;
97
+ } trilogy_conn_t;
98
+
99
+ /* trilogy_init - Initialize a pre-allocated trilogy_conn_t pointer.
100
+ *
101
+ * conn - A pre-allocated trilogy_conn_t pointer.
102
+ *
103
+ * Return values:
104
+ * TRILOGY_OK - The trilogy_conn_t pointer was properly initialized
105
+ * TRILOGY_SYSERR - A system error occurred, check errno.
106
+ */
107
+ int trilogy_init(trilogy_conn_t *conn);
108
+
109
+ /* trilogy_flush_writes - Attempt to flush the internal packet buffer to the
110
+ * network. This must be used if a `_send` function returns TRILOGY_AGAIN, and
111
+ * should continue to be called until it returns a value other than
112
+ * TRILOGY_AGAIN.
113
+ *
114
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
115
+ * undefined.
116
+ *
117
+ * Return values:
118
+ * TRILOGY_OK - The entire packet buffer has been written to the network.
119
+ * TRILOGY_AGAIN - Only part of the packet buffer was written to the network or
120
+ * the socket wasn't ready for writing. The caller should wait
121
+ * for writabilty using `conn->sock`. Then call this function
122
+ * until it returns a different value.
123
+ * TRILOGY_SYSERR - A system error occurred, check errno.
124
+ */
125
+ int trilogy_flush_writes(trilogy_conn_t *conn);
126
+
127
+ /* trilogy_connect_send - Create a socket and attempt initial connection to the
128
+ * server.
129
+ *
130
+ * conn - A pre-initialized trilogy_conn_t pointer.
131
+ * addr - A pre-initialized trilogy_sockopt_t pointer with the connection
132
+ * parameters.
133
+ *
134
+ * Return values:
135
+ * TRILOGY_OK - The socket was created and the initial connection has been
136
+ * established.
137
+ * TRILOGY_SYSERR - A system error occurred, check errno.
138
+ */
139
+ int trilogy_connect_send(trilogy_conn_t *conn, const trilogy_sockopt_t *opts);
140
+
141
+ /* trilogy_connect_send_socket - Attempt initial connection to the server using an
142
+ * existing trilogy_sock_t. The socket must _not_ have been connected yet.
143
+ *
144
+ * sock - An instance of trilogy_sock_t
145
+ *
146
+ * Return values:
147
+ * TRILOGY_OK - The socket was created and the initial connection has been
148
+ * established.
149
+ * TRILOGY_SYSERR - A system error occurred, check errno.
150
+ */
151
+ int trilogy_connect_send_socket(trilogy_conn_t *conn, trilogy_sock_t *sock);
152
+
153
+ /* trilogy_connect_recv - Read the initial handshake from the server.
154
+ *
155
+ * This should be called after trilogy_connect_send returns TRILOGY_OK. Calling
156
+ * this at any other time during the connection lifecycle is undefined.
157
+ *
158
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected
159
+ * trilogy_conn_t is undefined.
160
+ * handshake_out - A pre-allocated trilogy_handshake_t pointer. If TRILOGY_OK is
161
+ * returned, this struct will be filled out and ready to use.
162
+ *
163
+ * Return values:
164
+ * TRILOGY_OK - The initial handshake packet was read off the
165
+ * network.
166
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
167
+ * should wait for readability using `conn->sock`.
168
+ * Then call this function again.
169
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
170
+ * packet.
171
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
172
+ * TRILOGY_SYSERR - A system error occurred, check errno.
173
+ */
174
+ int trilogy_connect_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake_out);
175
+
176
+ /* trilogy_ssl_request_send - Send an SSL handshake request to the server.
177
+ *
178
+ * This should be called after a successful connection to the server. Calling
179
+ * this at any other time during the connection lifecycle is undefined. It is an
180
+ * error to call this function if TRILOGY_CAPABILITIES_SSL was not set by the
181
+ * server.
182
+ *
183
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected
184
+ * trilogy_conn_t is undefined.
185
+ *
186
+ * Return values:
187
+ * TRILOGY_OK - Authorization info was successfully sent to the server.
188
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
189
+ * for writeability using `conn->sock`. Then call
190
+ * trilogy_flush_writes.
191
+ * TRILOGY_SYSERR - A system error occurred, check errno.
192
+ */
193
+ int trilogy_ssl_request_send(trilogy_conn_t *conn);
194
+
195
+ /* trilogy_auth_send - Send a authorization info to the server.
196
+ *
197
+ * This should be called after a successful connection to the server. Calling
198
+ * this at any other time during the connection lifecycle is undefined.
199
+ *
200
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected
201
+ * trilogy_conn_t is undefined.
202
+ * handshake - A pre-initialized trilogy_handshake_t pointer.
203
+ *
204
+ * Return values:
205
+ * TRILOGY_OK - Authorization info was successfully sent to the server.
206
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
207
+ * for writeability using `conn->sock`. Then call
208
+ * trilogy_flush_writes.
209
+ * TRILOGY_SYSERR - A system error occurred, check errno.
210
+ */
211
+ int trilogy_auth_send(trilogy_conn_t *conn, const trilogy_handshake_t *handshake);
212
+
213
+ /* trilogy_auth_recv - Read the authorization response from the server.
214
+ *
215
+ * This should be called after all data written by trilogy_auth_send is flushed to
216
+ * the network. Calling this at any other time during the connection lifecycle
217
+ * is undefined.
218
+ *
219
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
220
+ * undefined.
221
+ *
222
+ * Return values:
223
+ * TRILOGY_OK - Authorization completed successfully. The
224
+ * connection is ready for commands.
225
+ * TRILOGY_AUTH_SWITCH - The server requested an auth switch. Use
226
+ * `trilogy_auth_switch_send` to reply with the
227
+ * confirmation of the switch.
228
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
229
+ * should wait for readability using `conn->sock`.
230
+ * Then call this function until it returns a
231
+ * different value.
232
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
233
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
234
+ * packet.
235
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
236
+ * TRILOGY_SYSERR - A system error occurred, check errno.
237
+ */
238
+ int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake);
239
+
240
+ /* trilogy_auth_switch_send - Send a reply after an authentication switch request.
241
+ *
242
+ * This should be called after the server requests and auth switch. Calling
243
+ * this at any other time during the connection lifecycle is undefined.
244
+ *
245
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is undefined.
246
+ * handshake - A pre-initialized trilogy_handshake_t pointer.
247
+ *
248
+ * Return values:
249
+ * TRILOGY_OK - Authorization info was successfully sent to the server.
250
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
251
+ * for writeability using `conn->sock`. Then call
252
+ * trilogy_flush_writes.
253
+ * TRILOGY_SYSERR - A system error occurred, check errno.
254
+ */
255
+ int trilogy_auth_switch_send(trilogy_conn_t *conn, const trilogy_handshake_t *handshake);
256
+
257
+ /* trilogy_change_db_send - Send a change database command to the server. This
258
+ * will change the default database for this connection.
259
+ *
260
+ * This should only be called while the connection is ready for commands.
261
+ *
262
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected
263
+ * trilogy_conn_t is undefined.
264
+ * name - The name of the database.
265
+ * name_len - The length of the database name in bytes.
266
+ *
267
+ * Return values:
268
+ * TRILOGY_OK - The change database command was successfully sent to the
269
+ * server.
270
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
271
+ * for writeability using `conn->sock`. Then call
272
+ * trilogy_flush_writes.
273
+ * TRILOGY_SYSERR - A system error occurred, check errno.
274
+ */
275
+ int trilogy_change_db_send(trilogy_conn_t *conn, const char *name, size_t name_len);
276
+
277
+ /* trilogy_change_db_recv - Read the change database command response from the
278
+ * server.
279
+ *
280
+ * This should be called after all data written by trilogy_change_db_send is
281
+ * flushed to the network. Calling this at any other time during the connection
282
+ * lifecycle is undefined.
283
+ *
284
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
285
+ * undefined.
286
+ *
287
+ * Return values:
288
+ * TRILOGY_OK - The change database command was successfully
289
+ * sent to the server.
290
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The
291
+ * caller should wait for readability using
292
+ * `conn->sock`. Then call this function until
293
+ * it returns a different value.
294
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
295
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
296
+ * packet.
297
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
298
+ * TRILOGY_SYSERR - A system error occurred, check errno.
299
+ */
300
+ int trilogy_change_db_recv(trilogy_conn_t *conn);
301
+
302
+ /* trilogy_query_send - Send a query command to the server.
303
+ *
304
+ * This should only be called while the connection is ready for commands.
305
+ *
306
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected
307
+ * trilogy_conn_t is undefined.
308
+ * query - The query string.
309
+ * query_len - The length of query string in bytes.
310
+ *
311
+ * Return values:
312
+ * TRILOGY_OK - The query command was successfully sent to the server.
313
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should
314
+ * wait for writeability using `conn->sock`. Then call
315
+ * trilogy_flush_writes.
316
+ * TRILOGY_SYSERR - A system error occurred, check errno.
317
+ */
318
+ int trilogy_query_send(trilogy_conn_t *conn, const char *query, size_t query_len);
319
+
320
+ /* trilogy_query_recv - Read the query command response from the server.
321
+ *
322
+ * This should be called after all data written by trilogy_query_send is flushed
323
+ * to the network. Calling this at any other time during the connection
324
+ * lifecycle is undefined.
325
+ *
326
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected
327
+ * trilogy_conn_t is undefined.
328
+ * column_count_out - Out parameter; If TRILOGY_HAVE_RESULTS is returned, this
329
+ * will be set to the number of columns in the result set.
330
+ *
331
+ * Return values:
332
+ * TRILOGY_OK - The query response was received and fully read.
333
+ * TRILOGY_HAVE_RESULTS - The query response was received and there are
334
+ * results to be read.
335
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
336
+ * should wait for readability using `conn->sock`.
337
+ * Then call this function until it returns a
338
+ * different value.
339
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
340
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
341
+ * packet.
342
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
343
+ * TRILOGY_SYSERR - A system error occurred, check errno.
344
+ */
345
+ int trilogy_query_recv(trilogy_conn_t *conn, uint64_t *column_count_out);
346
+
347
+ /* trilogy_read_column - Read a column from the result set.
348
+ *
349
+ * This should be called as many times as there are columns in the result set.
350
+ * Calling this more times than that is undefined. This should also only be
351
+ * called after a query command has completed and returned TRILOGY_HAVE_RESULTS.
352
+ * Calling this at any other time during the connection lifecycle is undefined.
353
+ *
354
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected
355
+ * trilogy_conn_t is undefined.
356
+ * column_out - Out parameter; A pointer to a pre-allocated trilogy_column_t. If
357
+ * TRILOGY_OK is returned this will be filled out. This value will be
358
+ * invalid after any other call to this API. The caller should make
359
+ * a copy if they want to keep the value around.
360
+ *
361
+ * Return values:
362
+ * TRILOGY_OK - The column was successfully read.
363
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
364
+ * should wait for readability using `conn->sock`.
365
+ * Then call this function until it returns a
366
+ * different value.
367
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
368
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
369
+ * packet.
370
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
371
+ * TRILOGY_SYSERR - A system error occurred, check errno.
372
+ */
373
+ int trilogy_read_column(trilogy_conn_t *conn, trilogy_column_t *column_out);
374
+
375
+ /* trilogy_read_row - Read a column from the result set.
376
+ *
377
+ * This should be called after reading all columns from the network. Calling
378
+ * this at any other time during the connection lifecycle is undefined.
379
+ *
380
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected
381
+ * trilogy_conn_t is undefined.
382
+ * values_out - Out parameter; A pre-allocated trilogy_value_t pointer, which will
383
+ * be filled out by this function. It should be allocated with
384
+ * enough space to hold a trilogy_value_t pointer for each column.
385
+ * Something like: `(sizeof(trilogy_value_t) * column_count)`. This
386
+ * pointer is invalid after any other call to this API. The caller
387
+ * should make a copy of the values inside if they want to keep
388
+ * them around.
389
+ *
390
+ * Return values:
391
+ * TRILOGY_OK - The query response was received and fully read.
392
+ * TRILOGY_EOF - There are no more rows to be read.
393
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
394
+ * should wait for readability using `conn->sock`.
395
+ * Then call this function until it returns a
396
+ * different value.
397
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
398
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
399
+ * packet.
400
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
401
+ * TRILOGY_SYSERR - A system error occurred, check errno.
402
+ */
403
+ int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out);
404
+
405
+ /* trilogy_drain_results - A convenience function to read and throw away the
406
+ * remaining rows from a result set. Any MySQL-compatible protocol requires that all
407
+ * responses from a command are read off the network before any other commands
408
+ * can be issued. A caller could otherwise do the same thing this function does
409
+ * by calling trilogy_read_row until it returns TRILOGY_EOF. But this call does that
410
+ * in a much more efficient manner by only reading packet frames then throwing
411
+ * them away, skipping the parsing of value information from inside each packet.
412
+ *
413
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
414
+ * undefined.
415
+ *
416
+ * Return values:
417
+ * TRILOGY_OK - The rest of the result was drained and the
418
+ * connection is ready for another command.
419
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
420
+ * should wait for readability using `conn->sock`.
421
+ * Then call this function until it returns a
422
+ * different value.
423
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
424
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
425
+ * packet.
426
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
427
+ * TRILOGY_SYSERR - A system error occurred, check errno.
428
+ */
429
+ int trilogy_drain_results(trilogy_conn_t *conn);
430
+
431
+ /* trilogy_ping_send - Send a ping command to the server.
432
+ *
433
+ * This should only be called while the connection is ready for commands.
434
+ *
435
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t
436
+ * is undefined.
437
+ *
438
+ * Return values:
439
+ * TRILOGY_OK - The ping command was successfully sent to the server.
440
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
441
+ * for writeability using `conn->sock`. Then call
442
+ * trilogy_flush_writes.
443
+ * TRILOGY_SYSERR - A system error occurred, check errno.
444
+ */
445
+ int trilogy_ping_send(trilogy_conn_t *conn);
446
+
447
+ /* trilogy_ping_recv - Read the ping command response from the server.
448
+ *
449
+ * This should be called after all data written by trilogy_ping_send is flushed to
450
+ * the network. Calling this at any other time during the connection lifecycle
451
+ * is undefined.
452
+ *
453
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
454
+ * undefined.
455
+ *
456
+ * Return values:
457
+ * TRILOGY_OK - The ping command was successfully sent to the
458
+ * server.
459
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
460
+ * should wait for readability using `conn->sock`.
461
+ * Then call this function until it returns a
462
+ * different value.
463
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
464
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
465
+ * packet.
466
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
467
+ * TRILOGY_SYSERR - A system error occurred, check errno.
468
+ */
469
+ int trilogy_ping_recv(trilogy_conn_t *conn);
470
+
471
+ /* trilogy_escape - Escape a string, making it safe to use in a query.
472
+ *
473
+ * This function assumes the input is in an ASCII-compatible encoding. Passing
474
+ * in a string in any other encoding is undefined and will likely corrupt the
475
+ * input. Potentially leaving the caller open to SQL-injection style attacks.
476
+ *
477
+ * If the TRILOGY_SERVER_STATUS_NO_BACKSLASH_ESCAPES flag is set, it will disable
478
+ * the use of the backslash character ("\") as an escape character. Making
479
+ * backslash an ordinary character like any other.
480
+ *
481
+ * That mode can be enabled at runtime by issuing setting the
482
+ * NO_BACKSLASH_ESCAPES sql mode. This can be done with a query like:
483
+ * "SET SQL_MODE=NO_BACKSLASH_ESCAPES"
484
+ *
485
+ * conn - A pre-initialized trilogy_conn_t pointer.
486
+ * str - The string to be escaped.
487
+ * len - The length of `str` in bytes.
488
+ * escaped_str_out - Out parameter; The dereferenced value of this pointer will
489
+ * point to the escaped version of `str` if TRILOGY_OK was
490
+ * returned.
491
+ * escaped_len_out - Out parameter; The length of the buffer `escaped_str_out`
492
+ * points to if TRILOGY_OK was returned.
493
+ *
494
+ * Return values:
495
+ * TRILOGY_OK - The input string has been processed.
496
+ * TRILOGY_SYSERR - A system error occurred, check errno.
497
+ */
498
+ int trilogy_escape(trilogy_conn_t *conn, const char *str, size_t len, const char **escaped_str_out,
499
+ size_t *escaped_len_out);
500
+
501
+ /* trilogy_close_send - Send a quit command to the server.
502
+ *
503
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
504
+ * undefined.
505
+ *
506
+ * Return values:
507
+ * TRILOGY_OK - The quit command was successfully sent to the server.
508
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
509
+ * for writeability using `conn->sock`. Then call
510
+ * trilogy_flush_writes.
511
+ * TRILOGY_SYSERR - A system error occurred, check errno.
512
+ */
513
+ int trilogy_close_send(trilogy_conn_t *conn);
514
+
515
+ /* trilogy_close_recv - Read the quit command response from the MySQL-compatible server.
516
+ *
517
+ * This should be called after all data written by trilogy_close_send is flushed
518
+ * to the network. Calling this at any other time during the connection
519
+ * lifecycle is undefined.
520
+ *
521
+ * conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
522
+ * a disconnected trilogy_conn_t will also return TRILOGY_OK.
523
+ *
524
+ * Return values:
525
+ * TRILOGY_OK - The quit command response successfully read from
526
+ * the server.
527
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
528
+ * should wait for readability using `conn->sock`.
529
+ * Then call this function until it returns a
530
+ * different value.
531
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
532
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
533
+ * packet.
534
+ * TRILOGY_SYSERR - A system error occurred, check errno.
535
+ */
536
+ int trilogy_close_recv(trilogy_conn_t *conn);
537
+
538
+ /* trilogy_free - Close the connection and free any internal buffers.
539
+ *
540
+ * conn - A pre-initialized trilogy_conn_t pointer.
541
+ *
542
+ * Returns nothing.
543
+ */
544
+ void trilogy_free(trilogy_conn_t *conn);
545
+
546
+ /* trilogy_stmt_prepare_send - Send a prepared statement prepare command to the server.
547
+ *
548
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
549
+ * undefined.
550
+ * stmt - A pointer to the buffer containing the statement to prepare.
551
+ * stmt_len - The length of the data buffer.
552
+ *
553
+ * Return values:
554
+ * TRILOGY_OK - The quit command was successfully sent to the server.
555
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
556
+ * for writeability using `conn->sock`. Then call
557
+ * trilogy_flush_writes.
558
+ * TRILOGY_SYSERR - A system error occurred, check errno.
559
+ */
560
+ int trilogy_stmt_prepare_send(trilogy_conn_t *conn, const char *stmt, size_t stmt_len);
561
+
562
+ /* trilogy_stmt_t - The trilogy client's prepared statement type.
563
+ */
564
+ typedef trilogy_stmt_ok_packet_t trilogy_stmt_t;
565
+
566
+ /* trilogy_stmt_prepare_recv - Read the prepared statement prepare command response
567
+ * from the MySQL-compatible server.
568
+ *
569
+ * This should be called after all data written by trilogy_stmt_prepare_send is flushed
570
+ * to the network. Calling this at any other time during the connection
571
+ * lifecycle is undefined.
572
+ *
573
+ * Following a successful call to this function, the caller will also need to read off
574
+ * `trilogy_stmt_t.column_count` parameters as column packets, then
575
+ * `trilogy_stmt_t.column_count` columns as column packets. This must be done before
576
+ * the socket will be command-ready again.
577
+ *
578
+ * conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
579
+ * a disconnected trilogy_conn_t will also return TRILOGY_OK.
580
+ * stmt_out - A pointer to a pre-allocated trilogy_stmt_t.
581
+ *
582
+ * Return values:
583
+ * TRILOGY_OK - The prepare command response successfully read from
584
+ * the server.
585
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
586
+ * should wait for readability using `conn->sock`.
587
+ * Then call this function until it returns a
588
+ * different value.
589
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
590
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
591
+ * packet.
592
+ * TRILOGY_SYSERR - A system error occurred, check errno.
593
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
594
+ */
595
+ int trilogy_stmt_prepare_recv(trilogy_conn_t *conn, trilogy_stmt_t *stmt_out);
596
+
597
+ /* trilogy_stmt_bind_data_send - Send a prepared statement bind long data command to the server.
598
+ *
599
+ * There is no pairing `trilogy_stmt_bind_data_recv` fucntion to this one because the server
600
+ * doesn't send a response to this command.
601
+ *
602
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
603
+ * undefined.
604
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement for which
605
+ * to bind the supplied parameter data to.
606
+ * param_num - The parameter index for which the supplied data should be bound to.
607
+ * data - A pointer to the buffer containing the data to be bound.
608
+ * data_len - The length of the data buffer.
609
+ *
610
+ * Return values:
611
+ * TRILOGY_OK - The bind data command was successfully sent to the server.
612
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
613
+ * for writeability using `conn->sock`. Then call
614
+ * trilogy_flush_writes.
615
+ * TRILOGY_SYSERR - A system error occurred, check errno.
616
+ */
617
+ int trilogy_stmt_bind_data_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint16_t param_num, uint8_t *data,
618
+ size_t data_len);
619
+
620
+ /* trilogy_stmt_execute_send - Send a prepared statement execute command to the server.
621
+ *
622
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
623
+ * undefined.
624
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
625
+ * requesting to execute.
626
+ * flags - The flags (TRILOGY_STMT_FLAGS_t) to be used with this execute command packet.
627
+ * binds - Pointer to an array of trilogy_binary_value_t's. The array size should match that
628
+ * of `trilogy_stmt_t.column_count`.
629
+ *
630
+ * Return values:
631
+ * TRILOGY_OK - The execute command was successfully sent to the server.
632
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
633
+ * for writeability using `conn->sock`. Then call
634
+ * trilogy_flush_writes.
635
+ * TRILOGY_SYSERR - A system error occurred, check errno.
636
+ */
637
+ int trilogy_stmt_execute_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint8_t flags, trilogy_binary_value_t *binds);
638
+
639
+ /* trilogy_stmt_execute_recv - Read the prepared statement execute command response
640
+ * from the MySQL-compatible server.
641
+ *
642
+ * This should be called after all data written by trilogy_stmt_execute_send is flushed
643
+ * to the network. Calling this at any other time during the connection
644
+ * lifecycle is undefined.
645
+ *
646
+ * conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
647
+ * a disconnected trilogy_conn_t will also return TRILOGY_OK.
648
+ * column_count_out - Out parameter; A pointer to a pre-allocated uint64_t. Represents the
649
+ * number of columns in the response.
650
+ *
651
+ * Return values:
652
+ * TRILOGY_OK - The prepare command response successfully read from
653
+ * the server.
654
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
655
+ * should wait for readability using `conn->sock`.
656
+ * Then call this function until it returns a
657
+ * different value.
658
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
659
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
660
+ * packet.
661
+ * TRILOGY_SYSERR - A system error occurred, check errno.
662
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
663
+ */
664
+ int trilogy_stmt_execute_recv(trilogy_conn_t *conn, uint64_t *column_count_out);
665
+
666
+ /* trilogy_stmt_read_row - Read a row from the prepared statement execute response.
667
+ *
668
+ * This should only be called after a sucessful call to trilogy_stmt_execute_recv.
669
+ * You should continue calling this until TRILOGY_EOF is returned. Denoting the end
670
+ * of the result set.
671
+ *
672
+ * conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
673
+ * a disconnected trilogy_conn_t will also return TRILOGY_OK.
674
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
675
+ * requesting to execute.
676
+ * columns - The list of columns from the prepared statement.
677
+ * column_count - The number of columns in prepared statement.
678
+ * values_out - Out parameter; A pointer to a pre-allocated array of
679
+ * trilogy_binary_value_t's. There must be enough space to fit all of the
680
+ * values. This can be computed with:
681
+ * `(sizeof(trilogy_binary_value_t) * column_count)`.
682
+ *
683
+ * Return values:
684
+ * TRILOGY_OK - The prepare command response successfully read from
685
+ * the server.
686
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
687
+ * should wait for readability using `conn->sock`.
688
+ * Then call this function until it returns a
689
+ * different value.
690
+ * TRILOGY_EOF - There are no more rows to read from the result set.
691
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
692
+ * TRILOGY_PROTOCOL_VIOLATION - Invalid length parsed for a TIME/DATETIME/TIMESTAMP value.
693
+ * TRILOGY_UNKNOWN_TYPE - An unsupported or unknown MySQL type was seen.
694
+ * TRILOGY_SYSERR - A system error occurred, check errno.
695
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
696
+ */
697
+ int trilogy_stmt_read_row(trilogy_conn_t *conn, trilogy_stmt_t *stmt, trilogy_column_packet_t *columns,
698
+ trilogy_binary_value_t *values_out);
699
+
700
+ /* trilogy_stmt_reset_send - Send a prepared statement reset command to the server.
701
+ *
702
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
703
+ * undefined.
704
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
705
+ * requesting to reset.
706
+ *
707
+ * Return values:
708
+ * TRILOGY_OK - The reset command was successfully sent to the server.
709
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
710
+ * for writeability using `conn->sock`. Then call
711
+ * trilogy_flush_writes.
712
+ * TRILOGY_SYSERR - A system error occurred, check errno.
713
+ */
714
+ int trilogy_stmt_reset_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt);
715
+
716
+ /* trilogy_stmt_reset_recv - Read the prepared statement reset command response
717
+ * from the MySQL-compatible server.
718
+ *
719
+ * This should be called after all data written by trilogy_stmt_reset_send is flushed
720
+ * to the network. Calling this at any other time during the connection
721
+ * lifecycle is undefined.
722
+ *
723
+ * conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
724
+ * a disconnected trilogy_conn_t will also return TRILOGY_OK.
725
+ *
726
+ * Return values:
727
+ * TRILOGY_OK - The reset command response successfully read from
728
+ * the server.
729
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
730
+ * should wait for readability using `conn->sock`.
731
+ * Then call this function until it returns a
732
+ * different value.
733
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
734
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
735
+ * packet.
736
+ * TRILOGY_SYSERR - A system error occurred, check errno.
737
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
738
+ */
739
+ int trilogy_stmt_reset_recv(trilogy_conn_t *conn);
740
+
741
+ /* trilogy_stmt_close_send - Send a prepared statement close command to the server.
742
+ *
743
+ * There is no pairing `trilogy_stmt_close_recv` fucntion to this one because the server
744
+ * doesn't send a response to this command.
745
+ *
746
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
747
+ * undefined.
748
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
749
+ * requesting to close.
750
+ *
751
+ * Return values:
752
+ * TRILOGY_OK - The close command was successfully sent to the server.
753
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
754
+ * for writeability using `conn->sock`. Then call
755
+ * trilogy_flush_writes.
756
+ * TRILOGY_SYSERR - A system error occurred, check errno.
757
+ */
758
+ int trilogy_stmt_close_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt);
759
+
760
+ #endif