1 /*-------------------------------------------------------------------------
2  *
3  * pgtclCmds.h
4  *	  declarations for the C functions which implement pg_* tcl commands
5  *
6  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * $Id: pgtclCmds.h 361 2013-10-08 01:59:23Z lbayuk $
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #ifndef PGTCLCMDS_H
15 #define PGTCLCMDS_H
16 
17 /* See Get_ErrorLine() macro below. Define this so 8.6-built stubs-enabled
18    extension will not crash if run under Tcl8.5.
19 */
20 #define USE_INTERP_ERRORLINE
21 
22 #include <tcl.h>
23 
24 #include "libpq-fe.h"
25 
26 /* Hack to deal with Tcl 8.4 const-ification without losing compatibility */
27 #ifndef CONST84
28 #define CONST84
29 #endif
30 
31 #ifndef FALSE
32 #define FALSE 0
33 #endif
34 #ifndef TRUE
35 #define TRUE 1
36 #endif
37 
38 #define RES_HARD_MAX 128
39 #define RES_START 16
40 
41 /* Runtime Tcl version, set in Pgtcl_Init(), and used in some commands */
42 extern double pgtcl_tcl_version;
43 
44 /*
45  * Each Pg_ConnectionId has a list of Pg_TclNotifies structs, one for each
46  * Tcl interpreter that has executed any pg_listens on the connection.
47  * We need this arrangement to be able to clean up if an interpreter is
48  * deleted while the connection remains open.  A free side benefit is that
49  * multiple interpreters can be registered to listen for the same notify
50  * name.  (All their callbacks will be called, but in an unspecified order.)
51  *
52  * We use the same approach for pg_on_connection_loss callbacks, but they
53  * are not kept in a hashtable since there's no name associated.
54  */
55 
56 typedef struct Pg_TclNotifies_s
57 {
58 	struct Pg_TclNotifies_s *next;		/* list link */
59 	Tcl_Interp *interp;			/* This Tcl interpreter */
60 
61 	/*
62 	 * NB: if interp == NULL, the interpreter is gone but we haven't yet
63 	 * got round to deleting the Pg_TclNotifies structure.
64 	 */
65 	Tcl_HashTable notify_hash;	/* Active pg_listen requests */
66 
67 	char	   *conn_loss_cmd;	/* pg_on_connection_loss cmd, or NULL */
68 }	Pg_TclNotifies;
69 
70 /*
71  * Hash table entries in notify_hash of Pg_TclNotifies have the following
72  * structure as their value. (Through 1.9.0, before the -pid option was
73  * added to pg_listen,  the hash table entry values were just the callback
74  * command string.)
75  */
76 typedef struct Pg_notify_command_s
77 {
78 	char	   *callback;		/* Callback command, dynamically allocated */
79 	char		use_pid;		/* If non-zero, pass PID argument */
80 } Pg_notify_command;
81 
82 typedef struct Pg_ConnectionId_s
83 {
84 	char		id[32];
85 	PGconn	   *conn;
86 	int			res_max;		/* Max number of results allocated */
87 	int			res_hardmax;	/* Absolute max to allow */
88 	int			res_count;		/* Current count of active results */
89 	int			res_last;		/* Optimize where to start looking */
90 	int			res_copy;		/* Query result with active copy */
91 	int			res_copyStatus; /* Copying status */
92 	PGresult  **results;		/* The results */
93 
94 	Pg_TclNotifies *notify_list;	/* head of list of notify info */
95 	int			notifier_running;		/* notify event source is live */
96 	Tcl_Channel notifier_channel;		/* Tcl_Channel on which notifier
97 										 * is listening */
98 	char	   *null_string;	/* String to return for NULL values */
99 	Tcl_Obj	   *notice_command;	/* Command to execute on getting a NOTICE */
100 	Tcl_Interp *interp;			/* Pointer to Tcl interpreter. This is
101 								   used by the notice handler callback. */
102 	char	   *copyBuf;		/* Buffer, if COPY TO record is too big */
103 	char	   *copyBufNext;	/* COPY TO overflow buffer remaining data */
104 	int			copyBufLeft;	/* COPY TO overflow buffer remaining bytes */
105 	Tcl_Obj    *callbackPtr;    /* Callback command prefix for async queries */
106 	Tcl_Interp *callbackInterp; /* Interp for the async query callback */
107 }	Pg_ConnectionId;
108 
109 /* Values of res_copyStatus */
110 #define RES_COPY_NONE	0
111 #define RES_COPY_INPROGRESS 1
112 #define RES_COPY_FIN	2
113 
114 
115 /*
116    If running with Tcl < 8.6, or with Tcl>=8.6 and the TCL_INTERP_ERRORLINE
117    macro is defined (see top of this file), then use the old access method
118    to directly access interp->errorLine.
119 
120    If using Tcl >= 8.6 without the compatibility fix, use the new access
121    method Tcl_GetErrorLine().
122 
123    The reason for using TCL_INTERP_ERRORLINE with 8.6 is that otherwise if
124    built with stubs on 8.6, and run under 8.5, it will crash when trying
125    to access errorLine.
126 */
127 #if defined(USE_INTERP_ERRORLINE) || (TCL_MAJOR_VERSION < 8) || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 6)
128 #define Get_ErrorLine(interp) interp->errorLine
129 #else
130 #define Get_ErrorLine(interp) Tcl_GetErrorLine(interp)
131 #endif
132 
133 
134 /* **************************/
135 /* registered Tcl functions */
136 /* **************************/
137 extern int Pg_conndefaults(
138   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
139 
140 extern int Pg_connect(
141   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
142 
143 extern int Pg_disconnect(
144   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
145 
146 extern int Pg_exec(
147   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
148 
149 extern int Pg_execute(
150   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
151 
152 extern int Pg_select(
153   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
154 
155 extern int Pg_result(
156   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
157 
158 extern int Pg_lo_open(
159   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
160 
161 extern int Pg_lo_close(
162   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
163 
164 extern int Pg_lo_read(
165   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
166 
167 extern int Pg_lo_write(
168   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
169 
170 extern int Pg_lo_lseek(
171   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
172 
173 extern int Pg_lo_creat(
174   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
175 
176 extern int Pg_lo_tell(
177   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
178 
179 extern int Pg_lo_unlink(
180   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
181 
182 extern int Pg_lo_import(
183   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
184 
185 extern int Pg_lo_export(
186   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
187 
188 extern int Pg_listen(
189   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
190 
191 extern int Pg_sendquery(
192   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
193 
194 extern int Pg_sendquery_params(
195   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
196 
197 extern int Pg_sendquery_prepared(
198   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
199 
200 extern int Pg_getresult(
201   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
202 
203 extern int Pg_isbusy(
204   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
205 
206 extern int Pg_blocking(
207   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
208 
209 extern int Pg_cancelrequest(
210   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
211 
212 extern int Pg_on_connection_loss(
213   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
214 
215 extern int Pg_escape_string(
216   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
217 
218 extern int Pg_quote(
219   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
220 
221 extern int Pg_escape_bytea(
222   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
223 
224 extern int Pg_unescape_bytea(
225   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
226 
227 extern int Pg_transaction_status(
228   ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
229 
230 extern int Pg_parameter_status(
231   ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
232 
233 extern int Pg_exec_prepared(
234   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
235 
236 extern int Pg_exec_params(
237   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
238 
239 extern int Pg_notice_handler(
240   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
241 
242 extern int Pg_result_callback(
243   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
244 
245 #ifdef HAVE_PQENCRYPTPASSWORD /* PostgreSQL >= 8.2.0 */
246 extern int Pg_encrypt_password(
247   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
248 #endif
249 
250 #ifdef HAVE_LO_TRUNCATE /* PostgreSQL >= 8.3.0 */
251 extern int Pg_lo_truncate(
252   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
253 #endif
254 
255 #ifdef HAVE_PQDESCRIBEPREPARED /* PostgreSQL >= 8.2.0 */
256 extern int Pg_describe_cursor(
257   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
258 extern int Pg_describe_prepared(
259   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
260 #endif
261 
262 extern int Pg_backend_pid(
263   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
264 
265 extern int Pg_server_version(
266   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
267 
268 #ifdef HAVE_LO_TELL64  /* PostgreSQL >= 9.3.0 */
269 extern int Pg_lo_tell64(
270   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
271 extern int Pg_lo_lseek64(
272   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
273 extern int Pg_lo_truncate64(
274   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
275 #endif
276 
277 #ifdef HAVE_PQESCAPELITERAL /* PostgreSQL >= 9.0 */
278 extern int Pg_escape_l_i(
279   ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
280 #endif
281 
282 #endif   /* PGTCLCMDS_H */
283