1 /*
2  * This file and its contents are licensed under the Timescale License.
3  * Please see the included NOTICE for copyright information and
4  * LICENSE-TIMESCALE for a copy of the license.
5  */
6 #ifndef TIMESCALEDB_TSL_REMOTE_ASYNC_H
7 #define TIMESCALEDB_TSL_REMOTE_ASYNC_H
8 
9 #include <postgres.h>
10 #include <libpq-fe.h>
11 #include <utils/timestamp.h>
12 
13 #include "stmt_params.h"
14 
15 typedef struct AsyncRequest AsyncRequest;
16 
17 typedef struct TSConnection TSConnection;
18 
19 typedef enum AsyncResponseType
20 {
21 	/* We got an entire result */
22 	RESPONSE_RESULT = 0,
23 	/* We got one row */
24 	RESPONSE_ROW,
25 	/* There was some kind of communication error */
26 	RESPONSE_COMMUNICATION_ERROR,
27 	/* Timeout while waiting for response */
28 	RESPONSE_TIMEOUT,
29 	/* Unexpected event or other error */
30 	RESPONSE_ERROR,
31 } AsyncResponseType;
32 
33 /* Base type for all responses */
34 typedef struct AsyncResponse AsyncResponse;
35 typedef struct AsyncResponseResult AsyncResponseResult;
36 typedef struct AsyncResponseCommunicationError AsyncResponseCommunicationError;
37 typedef struct AsyncResponseError AsyncResponseError;
38 typedef struct AsyncRequestSet AsyncRequestSet;
39 
40 typedef struct PreparedStmt PreparedStmt;
41 
42 /* Notes on naming conventions used in functions:
43  *
44  * Parameters named sql_statement take a string with single sql statement (as opposed to multiple
45  * statements)
46  *
47  * function endings:
48  * * _any_response return any responses including errors and timeouts
49  * * _any_result return a result which may be an error or success, but throw errors for
50  * communication errors and timeouts
51  * * _ok_result return successful results, throwing errors otherwise.
52  * * _ok_command returns void on successful commands, throwing errors otherwise.
53  *
54  */
55 
56 /* Async Request */
57 
58 typedef void (*async_response_callback)(AsyncRequest *m, AsyncResponse *, void *data);
59 
60 #define TS_NO_TIMEOUT DT_NOBEGIN
61 
62 extern AsyncRequest *async_request_send_with_stmt_params_elevel_res_format(
63 	TSConnection *conn, const char *sql_statement, StmtParams *params, int elevel, int res_format);
64 
65 #define async_request_send_with_params(conn, sql_statement, params, res_format)                    \
66 	async_request_send_with_stmt_params_elevel_res_format(conn,                                    \
67 														  sql_statement,                           \
68 														  params,                                  \
69 														  ERROR,                                   \
70 														  res_format)
71 #define async_request_send_with_params_elevel(conn, sql_statement, params, elevel)                 \
72 	async_request_send_with_stmt_params_elevel_res_format(conn,                                    \
73 														  sql_statement,                           \
74 														  params,                                  \
75 														  elevel,                                  \
76 														  FORMAT_TEXT)
77 #define async_request_send_binary(conn, sql_statement)                                             \
78 	async_request_send_with_stmt_params_elevel_res_format(conn,                                    \
79 														  sql_statement,                           \
80 														  NULL,                                    \
81 														  ERROR,                                   \
82 														  FORMAT_BINARY)
83 #define async_request_send_with_error(conn, sql_statement, elevel)                                 \
84 	async_request_send_with_stmt_params_elevel_res_format(conn,                                    \
85 														  sql_statement,                           \
86 														  NULL,                                    \
87 														  elevel,                                  \
88 														  FORMAT_TEXT)
89 #define async_request_send(conn, sql_statement)                                                    \
90 	async_request_send_with_error(conn, sql_statement, ERROR)
91 
92 extern AsyncRequest *async_request_send_prepare(TSConnection *conn, const char *sql_statement,
93 												int n_params);
94 extern AsyncRequest *async_request_send_prepared_stmt(PreparedStmt *stmt,
95 													  const char *const *paramValues);
96 extern AsyncRequest *async_request_send_prepared_stmt_with_params(PreparedStmt *stmt,
97 																  StmtParams *params,
98 																  int res_format);
99 
100 extern void async_request_attach_user_data(AsyncRequest *req, void *user_data);
101 extern void async_request_set_response_callback(AsyncRequest *req, async_response_callback cb,
102 												void *user_data);
103 extern bool async_request_set_single_row_mode(AsyncRequest *req);
104 extern TSConnection *async_request_get_connection(AsyncRequest *req);
105 extern AsyncResponseResult *async_request_wait_ok_result(AsyncRequest *request);
106 extern AsyncResponseResult *async_request_wait_any_result(AsyncRequest *request);
107 extern AsyncResponse *async_request_cleanup_result(AsyncRequest *req, TimestampTz endtime);
108 
109 /* Returns on successful commands, throwing errors otherwise */
110 extern void async_request_wait_ok_command(AsyncRequest *set);
111 extern PreparedStmt *async_request_wait_prepared_statement(AsyncRequest *request);
112 
113 /* Async Response */
114 extern void async_response_close(AsyncResponse *res);
115 extern void async_response_report_error(AsyncResponse *res, int elevel);
116 extern void async_response_report_error_or_close(AsyncResponse *res, int elevel);
117 
118 extern AsyncResponseType async_response_get_type(AsyncResponse *res);
119 extern void async_response_result_close(AsyncResponseResult *res);
120 extern PGresult *async_response_result_get_pg_result(AsyncResponseResult *res);
121 extern void *async_response_result_get_user_data(AsyncResponseResult *res);
122 extern AsyncRequest *async_response_result_get_request(AsyncResponseResult *res);
123 extern PreparedStmt *async_response_result_generate_prepared_stmt(AsyncResponseResult *res);
124 
125 /* Async Request Set */
126 extern AsyncRequestSet *async_request_set_create(void);
127 extern void async_request_set_add(AsyncRequestSet *set, AsyncRequest *req);
128 #define async_request_set_add_sql(set, conn, sql)                                                  \
129 	async_request_set_add(set, async_request_send(conn, sql))
130 
131 /* Return any response, including communication errors and timeouts */
132 extern AsyncResponse *async_request_set_wait_any_response_deadline(AsyncRequestSet *set,
133 																   TimestampTz endtime);
134 
135 #define async_request_set_wait_any_response(set)                                                   \
136 	async_request_set_wait_any_response_deadline(set, TS_NO_TIMEOUT)
137 
138 /* Return only successful results, throwing errors otherwise */
139 extern AsyncResponseResult *async_request_set_wait_ok_result(AsyncRequestSet *set);
140 
141 extern void async_request_set_wait_all_ok_commands(AsyncRequestSet *set);
142 
143 /* Return any results (success or failure), but throw errors on communication failures and timeouts
144  */
145 extern AsyncResponseResult *async_request_set_wait_any_result(AsyncRequestSet *set);
146 
147 /* Consume any pending response and throw it away */
148 extern void async_request_discard_response(AsyncRequest *req);
149 
150 /* Prepared Statements */
151 extern void prepared_stmt_close(PreparedStmt *stmt);
152 
153 #endif /* TIMESCALEDB_TSL_REMOTE_ASYNC_H */
154