1 /*
2  * PyGreSQL - a Python interface for the PostgreSQL database.
3  *
4  * The connection object - this file is part a of the C extension module.
5  *
6  * Copyright (c) 2020 by the PyGreSQL Development Team
7  *
8  * Please see the LICENSE.TXT file for specific restrictions.
9  */
10 
11 /* Deallocate connection object. */
12 static void
conn_dealloc(connObject * self)13 conn_dealloc(connObject *self)
14 {
15     if (self->cnx) {
16         Py_BEGIN_ALLOW_THREADS
17         PQfinish(self->cnx);
18         Py_END_ALLOW_THREADS
19     }
20     Py_XDECREF(self->cast_hook);
21     Py_XDECREF(self->notice_receiver);
22     PyObject_Del(self);
23 }
24 
25 /* Get connection attributes. */
26 static PyObject *
conn_getattr(connObject * self,PyObject * nameobj)27 conn_getattr(connObject *self, PyObject *nameobj)
28 {
29     const char *name = PyStr_AsString(nameobj);
30 
31     /*
32      * Although we could check individually, there are only a few
33      * attributes that don't require a live connection and unless someone
34      * has an urgent need, this will have to do.
35      */
36 
37     /* first exception - close which returns a different error */
38     if (strcmp(name, "close") && !self->cnx) {
39         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
40         return NULL;
41     }
42 
43     /* list PostgreSQL connection fields */
44 
45     /* postmaster host */
46     if (!strcmp(name, "host")) {
47         char *r = PQhost(self->cnx);
48         if (!r || r[0] == '/') /* Pg >= 9.6 can return a Unix socket path */
49             r = "localhost";
50         return PyStr_FromString(r);
51     }
52 
53     /* postmaster port */
54     if (!strcmp(name, "port"))
55         return PyInt_FromLong(atol(PQport(self->cnx)));
56 
57     /* selected database */
58     if (!strcmp(name, "db"))
59         return PyStr_FromString(PQdb(self->cnx));
60 
61     /* selected options */
62     if (!strcmp(name, "options"))
63         return PyStr_FromString(PQoptions(self->cnx));
64 
65     /* error (status) message */
66     if (!strcmp(name, "error"))
67         return PyStr_FromString(PQerrorMessage(self->cnx));
68 
69     /* connection status : 1 - OK, 0 - BAD */
70     if (!strcmp(name, "status"))
71         return PyInt_FromLong(PQstatus(self->cnx) == CONNECTION_OK ? 1 : 0);
72 
73     /* provided user name */
74     if (!strcmp(name, "user"))
75         return PyStr_FromString(PQuser(self->cnx));
76 
77     /* protocol version */
78     if (!strcmp(name, "protocol_version"))
79         return PyInt_FromLong(PQprotocolVersion(self->cnx));
80 
81     /* backend version */
82     if (!strcmp(name, "server_version"))
83         return PyInt_FromLong(PQserverVersion(self->cnx));
84 
85     /* descriptor number of connection socket */
86     if (!strcmp(name, "socket")) {
87         return PyInt_FromLong(PQsocket(self->cnx));
88     }
89 
90     /* PID of backend process */
91     if (!strcmp(name, "backend_pid")) {
92         return PyInt_FromLong(PQbackendPID(self->cnx));
93     }
94 
95     /* whether the connection uses SSL */
96     if (!strcmp(name, "ssl_in_use")) {
97 #ifdef SSL_INFO
98         if (PQsslInUse(self->cnx)) {
99             Py_INCREF(Py_True); return Py_True;
100         }
101         else {
102             Py_INCREF(Py_False); return Py_False;
103         }
104 #else
105         set_error_msg(NotSupportedError, "SSL info functions not supported");
106         return NULL;
107 #endif
108     }
109 
110     /* SSL attributes */
111     if (!strcmp(name, "ssl_attributes")) {
112 #ifdef SSL_INFO
113         return get_ssl_attributes(self->cnx);
114 #else
115         set_error_msg(NotSupportedError, "SSL info functions not supported");
116         return NULL;
117 #endif
118     }
119 
120     return PyObject_GenericGetAttr((PyObject *) self, nameobj);
121 }
122 
123 /* Check connection validity. */
124 static int
_check_cnx_obj(connObject * self)125 _check_cnx_obj(connObject *self)
126 {
127     if (!self || !self->valid || !self->cnx) {
128         set_error_msg(OperationalError, "Connection has been closed");
129         return 0;
130     }
131     return 1;
132 }
133 
134 /* Create source object. */
135 static char conn_source__doc__[] =
136 "source() -- create a new source object for this connection";
137 
138 static PyObject *
conn_source(connObject * self,PyObject * noargs)139 conn_source(connObject *self, PyObject *noargs)
140 {
141     sourceObject *source_obj;
142 
143     /* checks validity */
144     if (!_check_cnx_obj(self)) {
145         return NULL;
146     }
147 
148     /* allocates new query object */
149     if (!(source_obj = PyObject_New(sourceObject, &sourceType))) {
150         return NULL;
151     }
152 
153     /* initializes internal parameters */
154     Py_XINCREF(self);
155     source_obj->pgcnx = self;
156     source_obj->result = NULL;
157     source_obj->valid = 1;
158     source_obj->arraysize = PG_ARRAYSIZE;
159 
160     return (PyObject *) source_obj;
161 }
162 
163 /* For a non-query result, set the appropriate error status,
164    return the appropriate value, and free the result set. */
165 static PyObject *
_conn_non_query_result(int status,PGresult * result,PGconn * cnx)166 _conn_non_query_result(int status, PGresult* result, PGconn *cnx)
167 {
168     switch (status) {
169         case PGRES_EMPTY_QUERY:
170             PyErr_SetString(PyExc_ValueError, "Empty query");
171             break;
172         case PGRES_BAD_RESPONSE:
173         case PGRES_FATAL_ERROR:
174         case PGRES_NONFATAL_ERROR:
175             set_error(ProgrammingError, "Cannot execute query",
176                 cnx, result);
177             break;
178         case PGRES_COMMAND_OK:
179             {   /* INSERT, UPDATE, DELETE */
180                 Oid oid = PQoidValue(result);
181 
182                 if (oid == InvalidOid) {  /* not a single insert */
183                     char *ret = PQcmdTuples(result);
184 
185                     if (ret[0]) {  /* return number of rows affected */
186                         PyObject *obj = PyStr_FromString(ret);
187                         PQclear(result);
188                         return obj;
189                     }
190                     PQclear(result);
191                     Py_INCREF(Py_None);
192                     return Py_None;
193                 }
194                 /* for a single insert, return the oid */
195                 PQclear(result);
196                 return PyInt_FromLong((long) oid);
197             }
198         case PGRES_COPY_OUT: /* no data will be received */
199         case PGRES_COPY_IN:
200             PQclear(result);
201             Py_INCREF(Py_None);
202             return Py_None;
203         default:
204             set_error_msg(InternalError, "Unknown result status");
205     }
206 
207     PQclear(result);
208     return NULL; /* error detected on query */
209  }
210 
211 /* Base method for execution of all different kinds of queries */
212 static PyObject *
_conn_query(connObject * self,PyObject * args,int prepared,int async)213 _conn_query(connObject *self, PyObject *args, int prepared, int async)
214 {
215     PyObject *query_str_obj, *param_obj = NULL;
216     PGresult* result;
217     queryObject* query_obj;
218     char *query;
219     int encoding, status, nparms = 0;
220 
221     if (!self->cnx) {
222         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
223         return NULL;
224     }
225 
226     /* get query args */
227     if (!PyArg_ParseTuple(args, "O|O", &query_str_obj, &param_obj)) {
228         return NULL;
229     }
230 
231     encoding = PQclientEncoding(self->cnx);
232 
233     if (PyBytes_Check(query_str_obj)) {
234         query = PyBytes_AsString(query_str_obj);
235         query_str_obj = NULL;
236     }
237     else if (PyUnicode_Check(query_str_obj)) {
238         query_str_obj = get_encoded_string(query_str_obj, encoding);
239         if (!query_str_obj) return NULL; /* pass the UnicodeEncodeError */
240         query = PyBytes_AsString(query_str_obj);
241     }
242     else {
243         PyErr_SetString(PyExc_TypeError,
244                         "Method query() expects a string as first argument");
245         return NULL;
246     }
247 
248     /* If param_obj is passed, ensure it's a non-empty tuple. We want to treat
249      * an empty tuple the same as no argument since we'll get that when the
250      * caller passes no arguments to db.query(), and historic behaviour was
251      * to call PQexec() in that case, which can execute multiple commands. */
252     if (param_obj) {
253         param_obj = PySequence_Fast(
254             param_obj, "Method query() expects a sequence as second argument");
255         if (!param_obj) {
256             Py_XDECREF(query_str_obj);
257             return NULL;
258         }
259         nparms = (int) PySequence_Fast_GET_SIZE(param_obj);
260 
261         /* if there's a single argument and it's a list or tuple, it
262          * contains the positional arguments. */
263         if (nparms == 1) {
264             PyObject *first_obj = PySequence_Fast_GET_ITEM(param_obj, 0);
265             if (PyList_Check(first_obj) || PyTuple_Check(first_obj)) {
266                 Py_DECREF(param_obj);
267                 param_obj = PySequence_Fast(first_obj, NULL);
268                 nparms = (int) PySequence_Fast_GET_SIZE(param_obj);
269             }
270         }
271     }
272 
273     /* gets result */
274     if (nparms) {
275         /* prepare arguments */
276         PyObject **str, **s;
277         const char **parms, **p;
278         register int i;
279 
280         str = (PyObject **) PyMem_Malloc((size_t) nparms * sizeof(*str));
281         parms = (const char **) PyMem_Malloc((size_t) nparms * sizeof(*parms));
282         if (!str || !parms) {
283             PyMem_Free((void *) parms); PyMem_Free(str);
284             Py_XDECREF(query_str_obj); Py_XDECREF(param_obj);
285             return PyErr_NoMemory();
286         }
287 
288         /* convert optional args to a list of strings -- this allows
289          * the caller to pass whatever they like, and prevents us
290          * from having to map types to OIDs */
291         for (i = 0, s = str, p = parms; i < nparms; ++i, ++p) {
292             PyObject *obj = PySequence_Fast_GET_ITEM(param_obj, i);
293 
294             if (obj == Py_None) {
295                 *p = NULL;
296             }
297             else if (PyBytes_Check(obj)) {
298                 *p = PyBytes_AsString(obj);
299             }
300             else if (PyUnicode_Check(obj)) {
301                 PyObject *str_obj = get_encoded_string(obj, encoding);
302                 if (!str_obj) {
303                     PyMem_Free((void *) parms);
304                     while (s != str) { s--; Py_DECREF(*s); }
305                     PyMem_Free(str);
306                     Py_XDECREF(query_str_obj);
307                     Py_XDECREF(param_obj);
308                     /* pass the UnicodeEncodeError */
309                     return NULL;
310                 }
311                 *s++ = str_obj;
312                 *p = PyBytes_AsString(str_obj);
313             }
314             else {
315                 PyObject *str_obj = PyObject_Str(obj);
316                 if (!str_obj) {
317                     PyMem_Free((void *) parms);
318                     while (s != str) { s--; Py_DECREF(*s); }
319                     PyMem_Free(str);
320                     Py_XDECREF(query_str_obj);
321                     Py_XDECREF(param_obj);
322                     PyErr_SetString(
323                         PyExc_TypeError,
324                         "Query parameter has no string representation");
325                     return NULL;
326                 }
327                 *s++ = str_obj;
328                 *p = PyStr_AsString(str_obj);
329             }
330         }
331 
332         Py_BEGIN_ALLOW_THREADS
333         if (async) {
334             status = PQsendQueryParams(self->cnx, query, nparms,
335                 NULL, (const char * const *)parms, NULL, NULL, 0);
336             result = NULL;
337         }
338         else {
339             result = prepared ?
340                 PQexecPrepared(self->cnx, query, nparms,
341                     parms, NULL, NULL, 0) :
342                 PQexecParams(self->cnx, query, nparms,
343                     NULL, parms, NULL, NULL, 0);
344             status = result != NULL;
345         }
346         Py_END_ALLOW_THREADS
347 
348         PyMem_Free((void *) parms);
349         while (s != str) { s--; Py_DECREF(*s); }
350         PyMem_Free(str);
351     }
352     else {
353         Py_BEGIN_ALLOW_THREADS
354         if (async) {
355             status = PQsendQuery(self->cnx, query);
356             result = NULL;
357         }
358         else {
359             result = prepared ?
360                 PQexecPrepared(self->cnx, query, 0,
361                     NULL, NULL, NULL, 0) :
362                 PQexec(self->cnx, query);
363             status = result != NULL;
364         }
365         Py_END_ALLOW_THREADS
366     }
367 
368     /* we don't need the query and its params any more */
369     Py_XDECREF(query_str_obj);
370     Py_XDECREF(param_obj);
371 
372     /* checks result validity */
373     if (!status) {
374         PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
375         return NULL;
376     }
377 
378     /* this may have changed the datestyle, so we reset the date format
379        in order to force fetching it newly when next time requested */
380     self->date_format = date_format; /* this is normally NULL */
381 
382     /* checks result status */
383     if (result && (status = PQresultStatus(result)) != PGRES_TUPLES_OK)
384         return _conn_non_query_result(status, result, self->cnx);
385 
386     if (!(query_obj = PyObject_New(queryObject, &queryType)))
387         return PyErr_NoMemory();
388 
389     /* stores result and returns object */
390     Py_XINCREF(self);
391     query_obj->pgcnx = self;
392     query_obj->result = result;
393     query_obj->async = async;
394     query_obj->encoding = encoding;
395     query_obj->current_row = 0;
396     if (async) {
397         query_obj->max_row = 0;
398         query_obj->num_fields = 0;
399         query_obj->col_types = NULL;
400     }
401     else {
402         query_obj->max_row = PQntuples(result);
403         query_obj->num_fields = PQnfields(result);
404         query_obj->col_types = get_col_types(result, query_obj->num_fields);
405         if (!query_obj->col_types) {
406             Py_DECREF(query_obj);
407             Py_DECREF(self);
408             return NULL;
409         }
410     }
411 
412     return (PyObject *) query_obj;
413 }
414 
415 /* Database query */
416 static char conn_query__doc__[] =
417 "query(sql, [arg]) -- create a new query object for this connection\n\n"
418 "You must pass the SQL (string) request and you can optionally pass\n"
419 "a tuple with positional parameters.\n";
420 
421 static PyObject *
conn_query(connObject * self,PyObject * args)422 conn_query(connObject *self, PyObject *args)
423 {
424     return _conn_query(self, args, 0, 0);
425 }
426 
427 /* Asynchronous database query */
428 static char conn_send_query__doc__[] =
429 "send_query(sql, [arg]) -- create a new asynchronous query for this connection\n\n"
430 "You must pass the SQL (string) request and you can optionally pass\n"
431 "a tuple with positional parameters.\n";
432 
433 static PyObject *
conn_send_query(connObject * self,PyObject * args)434 conn_send_query(connObject *self, PyObject *args)
435 {
436     return _conn_query(self, args, 0, 1);
437 }
438 
439 /* Execute prepared statement. */
440 static char conn_query_prepared__doc__[] =
441 "query_prepared(name, [arg]) -- execute a prepared statement\n\n"
442 "You must pass the name (string) of the prepared statement and you can\n"
443 "optionally pass a tuple with positional parameters.\n";
444 
445 static PyObject *
conn_query_prepared(connObject * self,PyObject * args)446 conn_query_prepared(connObject *self, PyObject *args)
447 {
448     return _conn_query(self, args, 1, 0);
449 }
450 
451 /* Create prepared statement. */
452 static char conn_prepare__doc__[] =
453 "prepare(name, sql) -- create a prepared statement\n\n"
454 "You must pass the name (string) of the prepared statement and the\n"
455 "SQL (string) request for later execution.\n";
456 
457 static PyObject *
conn_prepare(connObject * self,PyObject * args)458 conn_prepare(connObject *self, PyObject *args)
459 {
460     char *name, *query;
461     Py_ssize_t name_length, query_length;
462     PGresult *result;
463 
464     if (!self->cnx) {
465         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
466         return NULL;
467     }
468 
469     /* reads args */
470     if (!PyArg_ParseTuple(args, "s#s#",
471         &name, &name_length, &query, &query_length))
472     {
473         PyErr_SetString(PyExc_TypeError,
474                         "Method prepare() takes two string arguments");
475         return NULL;
476     }
477 
478     /* create prepared statement */
479     Py_BEGIN_ALLOW_THREADS
480     result = PQprepare(self->cnx, name, query, 0, NULL);
481     Py_END_ALLOW_THREADS
482     if (result && PQresultStatus(result) == PGRES_COMMAND_OK) {
483         PQclear(result);
484         Py_INCREF(Py_None);
485         return Py_None; /* success */
486     }
487     set_error(ProgrammingError, "Cannot create prepared statement",
488         self->cnx, result);
489     if (result)
490         PQclear(result);
491     return NULL; /* error */
492 }
493 
494 /* Describe prepared statement. */
495 static char conn_describe_prepared__doc__[] =
496 "describe_prepared(name) -- describe a prepared statement\n\n"
497 "You must pass the name (string) of the prepared statement.\n";
498 
499 static PyObject *
conn_describe_prepared(connObject * self,PyObject * args)500 conn_describe_prepared(connObject *self, PyObject *args)
501 {
502     char *name;
503     Py_ssize_t name_length;
504     PGresult *result;
505 
506     if (!self->cnx) {
507         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
508         return NULL;
509     }
510 
511     /* reads args */
512     if (!PyArg_ParseTuple(args, "s#", &name, &name_length)) {
513         PyErr_SetString(PyExc_TypeError,
514                         "Method prepare() takes a string argument");
515         return NULL;
516     }
517 
518     /* describe prepared statement */
519     Py_BEGIN_ALLOW_THREADS
520     result = PQdescribePrepared(self->cnx, name);
521     Py_END_ALLOW_THREADS
522     if (result && PQresultStatus(result) == PGRES_COMMAND_OK) {
523         queryObject *query_obj = PyObject_New(queryObject, &queryType);
524         if (!query_obj)
525             return PyErr_NoMemory();
526         Py_XINCREF(self);
527         query_obj->pgcnx = self;
528         query_obj->result = result;
529         query_obj->encoding = PQclientEncoding(self->cnx);
530         query_obj->current_row = 0;
531         query_obj->max_row = PQntuples(result);
532         query_obj->num_fields = PQnfields(result);
533         query_obj->col_types = get_col_types(result, query_obj->num_fields);
534         return (PyObject *) query_obj;
535     }
536     set_error(ProgrammingError, "Cannot describe prepared statement",
537         self->cnx, result);
538     if (result)
539         PQclear(result);
540     return NULL; /* error */
541 }
542 
543 #ifdef DIRECT_ACCESS
544 static char conn_putline__doc__[] =
545 "putline(line) -- send a line directly to the backend";
546 
547 /* Direct access function: putline. */
548 static PyObject *
conn_putline(connObject * self,PyObject * args)549 conn_putline(connObject *self, PyObject *args)
550 {
551     char *line;
552     Py_ssize_t line_length;
553 
554     if (!self->cnx) {
555         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
556         return NULL;
557     }
558 
559     /* reads args */
560     if (!PyArg_ParseTuple(args, "s#", &line, &line_length)) {
561         PyErr_SetString(PyExc_TypeError,
562                         "Method putline() takes a string argument");
563         return NULL;
564     }
565 
566     /* sends line to backend */
567     if (PQputline(self->cnx, line)) {
568         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
569         return NULL;
570     }
571     Py_INCREF(Py_None);
572     return Py_None;
573 }
574 
575 /* Direct access function: getline. */
576 static char conn_getline__doc__[] =
577 "getline() -- get a line directly from the backend";
578 
579 static PyObject *
conn_getline(connObject * self,PyObject * noargs)580 conn_getline(connObject *self, PyObject *noargs)
581 {
582     char line[MAX_BUFFER_SIZE];
583     PyObject *str = NULL;     /* GCC */
584 
585     if (!self->cnx) {
586         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
587         return NULL;
588     }
589 
590     /* gets line */
591     switch (PQgetline(self->cnx, line, MAX_BUFFER_SIZE)) {
592         case 0:
593             str = PyStr_FromString(line);
594             break;
595         case 1:
596             PyErr_SetString(PyExc_MemoryError, "Buffer overflow");
597             str = NULL;
598             break;
599         case EOF:
600             Py_INCREF(Py_None);
601             str = Py_None;
602             break;
603     }
604 
605     return str;
606 }
607 
608 /* Direct access function: end copy. */
609 static char conn_endcopy__doc__[] =
610 "endcopy() -- synchronize client and server";
611 
612 static PyObject *
conn_endcopy(connObject * self,PyObject * noargs)613 conn_endcopy(connObject *self, PyObject *noargs)
614 {
615     if (!self->cnx) {
616         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
617         return NULL;
618     }
619 
620     /* ends direct copy */
621     if (PQendcopy(self->cnx)) {
622         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
623         return NULL;
624     }
625     Py_INCREF(Py_None);
626     return Py_None;
627 }
628 
629 /* Direct access function: set blocking status. */
630 static char conn_set_non_blocking__doc__[] =
631 "set_non_blocking() -- set the non-blocking status of the connection";
632 
633 static PyObject *
conn_set_non_blocking(connObject * self,PyObject * args)634 conn_set_non_blocking(connObject *self, PyObject *args)
635 {
636     int non_blocking;
637 
638     if (!self->cnx) {
639         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
640         return NULL;
641     }
642 
643     if (!PyArg_ParseTuple(args, "i", &non_blocking)) {
644         PyErr_SetString(PyExc_TypeError, "setnonblocking(tf), with boolean.");
645         return NULL;
646     }
647 
648     if (PQsetnonblocking(self->cnx, non_blocking) < 0) {
649         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
650         return NULL;
651     }
652     Py_INCREF(Py_None);
653     return Py_None;
654 }
655 
656 /* Direct access function: get blocking status. */
657 static char conn_is_non_blocking__doc__[] =
658 "is_non_blocking() -- report the blocking status of the connection";
659 
660 static PyObject *
conn_is_non_blocking(connObject * self,PyObject * args)661 conn_is_non_blocking(connObject *self, PyObject *args)
662 {
663     int rc;
664 
665     if (!self->cnx) {
666         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
667         return NULL;
668     }
669 
670     if (!PyArg_ParseTuple(args, "")) {
671         PyErr_SetString(PyExc_TypeError,
672             "method is_non_blocking() takes no parameters");
673         return NULL;
674     }
675 
676     rc = PQisnonblocking(self->cnx);
677     if (rc < 0) {
678         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
679         return NULL;
680     }
681 
682     return PyBool_FromLong(rc);
683 }
684 #endif /* DIRECT_ACCESS */
685 
686 
687 /* Insert table */
688 static char conn_inserttable__doc__[] =
689 "inserttable(table, data, [columns]) -- insert list into table\n\n"
690 "The fields in the list must be in the same order as in the table\n"
691 "or in the list of columns if one is specified.\n";
692 
693 static PyObject *
conn_inserttable(connObject * self,PyObject * args)694 conn_inserttable(connObject *self, PyObject *args)
695 {
696     PGresult *result;
697     char *table, *buffer, *bufpt;
698     int encoding;
699     size_t bufsiz;
700     PyObject *list, *sublist, *item, *columns = NULL;
701     PyObject *(*getitem) (PyObject *, Py_ssize_t);
702     PyObject *(*getsubitem) (PyObject *, Py_ssize_t);
703     PyObject *(*getcolumn) (PyObject *, Py_ssize_t);
704     Py_ssize_t i, j, m, n = 0;
705 
706     if (!self->cnx) {
707         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
708         return NULL;
709     }
710 
711     /* gets arguments */
712     if (!PyArg_ParseTuple(args, "sO|O", &table, &list, &columns)) {
713         PyErr_SetString(
714             PyExc_TypeError,
715             "Method inserttable() expects a string and a list as arguments");
716         return NULL;
717     }
718 
719     /* checks list type */
720     if (PyList_Check(list)) {
721         m = PyList_Size(list);
722         getitem = PyList_GetItem;
723     }
724     else if (PyTuple_Check(list)) {
725         m = PyTuple_Size(list);
726         getitem = PyTuple_GetItem;
727     }
728     else {
729         PyErr_SetString(
730             PyExc_TypeError,
731             "Method inserttable() expects a list or a tuple"
732             " as second argument");
733         return NULL;
734     }
735 
736     /* checks columns type */
737     if (columns) {
738         if (PyList_Check(columns)) {
739             n = PyList_Size(columns);
740             getcolumn = PyList_GetItem;
741         }
742         else if (PyTuple_Check(columns)) {
743             n = PyTuple_Size(columns);
744             getcolumn = PyTuple_GetItem;
745         }
746         else {
747             PyErr_SetString(
748                 PyExc_TypeError,
749                 "Method inserttable() expects a list or a tuple"
750                 " as third argument");
751             return NULL;
752         }
753         if (!n) {
754             /* no columns specified, nothing to do */
755             Py_INCREF(Py_None);
756             return Py_None;
757         }
758     }
759 
760     /* allocate buffer */
761     if (!(buffer = PyMem_Malloc(MAX_BUFFER_SIZE)))
762         return PyErr_NoMemory();
763 
764     encoding = PQclientEncoding(self->cnx);
765 
766     /* starts query */
767     bufpt = buffer;
768     table = PQescapeIdentifier(self->cnx, table, strlen(table));
769     bufpt += sprintf(bufpt, "copy %s", table);
770     PQfreemem(table);
771     if (columns) {
772         /* adds a string like f" ({','.join(columns)})" */
773         bufpt += sprintf(bufpt, " (");
774         for (j = 0; j < n; ++j) {
775             PyObject *obj = getcolumn(columns, j);
776             ssize_t slen;
777             char *col;
778 
779             if (PyBytes_Check(obj)) {
780                 PyBytes_AsStringAndSize(obj, &col, &slen);
781             }
782             else if (PyUnicode_Check(obj)) {
783                 obj = get_encoded_string(obj, encoding);
784                 if (!obj) return NULL; /* pass the UnicodeEncodeError */
785                 PyBytes_AsStringAndSize(obj, &col, &slen);
786                 Py_DECREF(obj);
787             } else {
788                 PyErr_SetString(
789                     PyExc_TypeError,
790                     "The third argument must contain only strings");
791             }
792             col = PQescapeIdentifier(self->cnx, col, (size_t) slen);
793             bufpt += sprintf(bufpt, "%s%s", col, j == n - 1 ? ")" : ",");
794             PQfreemem(col);
795         }
796     }
797     sprintf(bufpt, " from stdin");
798 
799     Py_BEGIN_ALLOW_THREADS
800     result = PQexec(self->cnx, buffer);
801     Py_END_ALLOW_THREADS
802 
803     if (!result) {
804         PyMem_Free(buffer);
805         PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
806         return NULL;
807     }
808 
809     PQclear(result);
810 
811     /* feed table */
812     for (i = 0; i < m; ++i) {
813         sublist = getitem(list, i);
814         if (PyTuple_Check(sublist)) {
815             j = PyTuple_Size(sublist);
816             getsubitem = PyTuple_GetItem;
817         }
818         else if (PyList_Check(sublist)) {
819             j = PyList_Size(sublist);
820             getsubitem = PyList_GetItem;
821         }
822         else {
823             PyErr_SetString(
824                 PyExc_TypeError,
825                 "The second argument must contain a tuple or a list");
826             return NULL;
827         }
828         if (i) {
829             if (j != n) {
830                 PyMem_Free(buffer);
831                 PyErr_SetString(
832                     PyExc_TypeError,
833                     "Arrays contained in second arg must have same size");
834                 return NULL;
835             }
836         }
837         else {
838             n = j; /* never used before this assignment */
839         }
840 
841         /* builds insert line */
842         bufpt = buffer;
843         bufsiz = MAX_BUFFER_SIZE - 1;
844 
845         for (j = 0; j < n; ++j) {
846             if (j) {
847                 *bufpt++ = '\t'; --bufsiz;
848             }
849 
850             item = getsubitem(sublist, j);
851 
852             /* convert item to string and append to buffer */
853             if (item == Py_None) {
854                 if (bufsiz > 2) {
855                     *bufpt++ = '\\'; *bufpt++ = 'N';
856                     bufsiz -= 2;
857                 }
858                 else
859                     bufsiz = 0;
860             }
861             else if (PyBytes_Check(item)) {
862                 const char* t = PyBytes_AsString(item);
863 
864                 while (*t && bufsiz) {
865                     if (*t == '\\' || *t == '\t' || *t == '\n') {
866                         *bufpt++ = '\\'; --bufsiz;
867                         if (!bufsiz) break;
868                     }
869                     *bufpt++ = *t++; --bufsiz;
870                 }
871             }
872             else if (PyUnicode_Check(item)) {
873                 PyObject *s = get_encoded_string(item, encoding);
874                 if (!s) {
875                     PyMem_Free(buffer);
876                     return NULL; /* pass the UnicodeEncodeError */
877                 }
878                 else {
879                     const char* t = PyBytes_AsString(s);
880 
881                     while (*t && bufsiz) {
882                         if (*t == '\\' || *t == '\t' || *t == '\n') {
883                             *bufpt++ = '\\'; --bufsiz;
884                             if (!bufsiz) break;
885                         }
886                         *bufpt++ = *t++; --bufsiz;
887                     }
888                     Py_DECREF(s);
889                 }
890             }
891             else if (PyInt_Check(item) || PyLong_Check(item)) {
892                 PyObject* s = PyObject_Str(item);
893                 const char* t = PyStr_AsString(s);
894 
895                 while (*t && bufsiz) {
896                     *bufpt++ = *t++; --bufsiz;
897                 }
898                 Py_DECREF(s);
899             }
900             else {
901                 PyObject* s = PyObject_Repr(item);
902                 const char* t = PyStr_AsString(s);
903 
904                 while (*t && bufsiz) {
905                     if (*t == '\\' || *t == '\t' || *t == '\n') {
906                         *bufpt++ = '\\'; --bufsiz;
907                         if (!bufsiz) break;
908                     }
909                     *bufpt++ = *t++; --bufsiz;
910                 }
911                 Py_DECREF(s);
912             }
913 
914             if (bufsiz <= 0) {
915                 PyMem_Free(buffer); return PyErr_NoMemory();
916             }
917 
918         }
919 
920         *bufpt++ = '\n'; *bufpt = '\0';
921 
922         /* sends data */
923         if (PQputline(self->cnx, buffer)) {
924             PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
925             PQendcopy(self->cnx);
926             PyMem_Free(buffer);
927             return NULL;
928         }
929     }
930 
931     /* ends query */
932     if (PQputline(self->cnx, "\\.\n")) {
933         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
934         PQendcopy(self->cnx);
935         PyMem_Free(buffer);
936         return NULL;
937     }
938 
939     if (PQendcopy(self->cnx)) {
940         PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
941         PyMem_Free(buffer);
942         return NULL;
943     }
944 
945     PyMem_Free(buffer);
946 
947     /* no error : returns nothing */
948     Py_INCREF(Py_None);
949     return Py_None;
950 }
951 
952 /* Get transaction state. */
953 static char conn_transaction__doc__[] =
954 "transaction() -- return the current transaction status";
955 
956 static PyObject *
conn_transaction(connObject * self,PyObject * noargs)957 conn_transaction(connObject *self, PyObject *noargs)
958 {
959     if (!self->cnx) {
960         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
961         return NULL;
962     }
963 
964     return PyInt_FromLong(PQtransactionStatus(self->cnx));
965 }
966 
967 /* Get parameter setting. */
968 static char conn_parameter__doc__[] =
969 "parameter(name) -- look up a current parameter setting";
970 
971 static PyObject *
conn_parameter(connObject * self,PyObject * args)972 conn_parameter(connObject *self, PyObject *args)
973 {
974     const char *name;
975 
976     if (!self->cnx) {
977         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
978         return NULL;
979     }
980 
981     /* get query args */
982     if (!PyArg_ParseTuple(args, "s", &name)) {
983         PyErr_SetString(PyExc_TypeError,
984                         "Method parameter() takes a string as argument");
985         return NULL;
986     }
987 
988     name = PQparameterStatus(self->cnx, name);
989 
990     if (name)
991         return PyStr_FromString(name);
992 
993     /* unknown parameter, return None */
994     Py_INCREF(Py_None);
995     return Py_None;
996 }
997 
998 /* Get current date format. */
999 static char conn_date_format__doc__[] =
1000 "date_format() -- return the current date format";
1001 
1002 static PyObject *
conn_date_format(connObject * self,PyObject * noargs)1003 conn_date_format(connObject *self, PyObject *noargs)
1004 {
1005     const char *fmt;
1006 
1007     if (!self->cnx) {
1008         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
1009         return NULL;
1010     }
1011 
1012     /* check if the date format is cached in the connection */
1013     fmt = self->date_format;
1014     if (!fmt) {
1015         fmt = date_style_to_format(PQparameterStatus(self->cnx, "DateStyle"));
1016         self->date_format = fmt; /* cache the result */
1017     }
1018 
1019     return PyStr_FromString(fmt);
1020 }
1021 
1022 #ifdef ESCAPING_FUNCS
1023 
1024 /* Escape literal */
1025 static char conn_escape_literal__doc__[] =
1026 "escape_literal(str) -- escape a literal constant for use within SQL";
1027 
1028 static PyObject *
conn_escape_literal(connObject * self,PyObject * string)1029 conn_escape_literal(connObject *self, PyObject *string)
1030 {
1031     PyObject *tmp_obj = NULL,  /* auxiliary string object */
1032              *to_obj;          /* string object to return */
1033     char *from,  /* our string argument as encoded string */
1034          *to;    /* the result as encoded string */
1035     Py_ssize_t from_length;    /* length of string */
1036     size_t to_length;          /* length of result */
1037     int encoding = -1;         /* client encoding */
1038 
1039     if (PyBytes_Check(string)) {
1040         PyBytes_AsStringAndSize(string, &from, &from_length);
1041     }
1042     else if (PyUnicode_Check(string)) {
1043         encoding = PQclientEncoding(self->cnx);
1044         tmp_obj = get_encoded_string(string, encoding);
1045         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
1046         PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
1047     }
1048     else {
1049         PyErr_SetString(
1050             PyExc_TypeError,
1051             "Method escape_literal() expects a string as argument");
1052         return NULL;
1053     }
1054 
1055     to = PQescapeLiteral(self->cnx, from, (size_t) from_length);
1056     to_length = strlen(to);
1057 
1058     Py_XDECREF(tmp_obj);
1059 
1060     if (encoding == -1)
1061         to_obj = PyBytes_FromStringAndSize(to, (Py_ssize_t) to_length);
1062     else
1063         to_obj = get_decoded_string(to, (Py_ssize_t) to_length, encoding);
1064     if (to)
1065         PQfreemem(to);
1066     return to_obj;
1067 }
1068 
1069 /* Escape identifier */
1070 static char conn_escape_identifier__doc__[] =
1071 "escape_identifier(str) -- escape an identifier for use within SQL";
1072 
1073 static PyObject *
conn_escape_identifier(connObject * self,PyObject * string)1074 conn_escape_identifier(connObject *self, PyObject *string)
1075 {
1076     PyObject *tmp_obj = NULL,  /* auxiliary string object */
1077              *to_obj;          /* string object to return */
1078     char *from,  /* our string argument as encoded string */
1079          *to;    /* the result as encoded string */
1080     Py_ssize_t from_length;    /* length of string */
1081     size_t to_length;          /* length of result */
1082     int encoding = -1;         /* client encoding */
1083 
1084     if (PyBytes_Check(string)) {
1085         PyBytes_AsStringAndSize(string, &from, &from_length);
1086     }
1087     else if (PyUnicode_Check(string)) {
1088         encoding = PQclientEncoding(self->cnx);
1089         tmp_obj = get_encoded_string(string, encoding);
1090         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
1091         PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
1092     }
1093     else {
1094         PyErr_SetString(
1095             PyExc_TypeError,
1096             "Method escape_identifier() expects a string as argument");
1097         return NULL;
1098     }
1099 
1100     to = PQescapeIdentifier(self->cnx, from, (size_t) from_length);
1101     to_length = strlen(to);
1102 
1103     Py_XDECREF(tmp_obj);
1104 
1105     if (encoding == -1)
1106         to_obj = PyBytes_FromStringAndSize(to, (Py_ssize_t) to_length);
1107     else
1108         to_obj = get_decoded_string(to, (Py_ssize_t) to_length, encoding);
1109     if (to)
1110         PQfreemem(to);
1111     return to_obj;
1112 }
1113 
1114 #endif /* ESCAPING_FUNCS */
1115 
1116 /* Escape string */
1117 static char conn_escape_string__doc__[] =
1118 "escape_string(str) -- escape a string for use within SQL";
1119 
1120 static PyObject *
conn_escape_string(connObject * self,PyObject * string)1121 conn_escape_string(connObject *self, PyObject *string)
1122 {
1123     PyObject *tmp_obj = NULL,  /* auxiliary string object */
1124              *to_obj;          /* string object to return */
1125     char *from,  /* our string argument as encoded string */
1126          *to;    /* the result as encoded string */
1127     Py_ssize_t from_length;    /* length of string */
1128     size_t to_length;          /* length of result */
1129     int encoding = -1;         /* client encoding */
1130 
1131     if (PyBytes_Check(string)) {
1132         PyBytes_AsStringAndSize(string, &from, &from_length);
1133     }
1134     else if (PyUnicode_Check(string)) {
1135         encoding = PQclientEncoding(self->cnx);
1136         tmp_obj = get_encoded_string(string, encoding);
1137         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
1138         PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
1139     }
1140     else {
1141         PyErr_SetString(
1142             PyExc_TypeError,
1143             "Method escape_string() expects a string as argument");
1144         return NULL;
1145     }
1146 
1147     to_length = 2 * (size_t) from_length + 1;
1148     if ((Py_ssize_t) to_length < from_length) { /* overflow */
1149         to_length = (size_t) from_length;
1150         from_length = (from_length - 1)/2;
1151     }
1152     to = (char *) PyMem_Malloc(to_length);
1153     to_length = PQescapeStringConn(self->cnx,
1154         to, from, (size_t) from_length, NULL);
1155 
1156     Py_XDECREF(tmp_obj);
1157 
1158     if (encoding == -1)
1159         to_obj = PyBytes_FromStringAndSize(to, (Py_ssize_t) to_length);
1160     else
1161         to_obj = get_decoded_string(to, (Py_ssize_t) to_length, encoding);
1162     PyMem_Free(to);
1163     return to_obj;
1164 }
1165 
1166 /* Escape bytea */
1167 static char conn_escape_bytea__doc__[] =
1168 "escape_bytea(data) -- escape binary data for use within SQL as type bytea";
1169 
1170 static PyObject *
conn_escape_bytea(connObject * self,PyObject * data)1171 conn_escape_bytea(connObject *self, PyObject *data)
1172 {
1173     PyObject *tmp_obj = NULL,  /* auxiliary string object */
1174              *to_obj;          /* string object to return */
1175     char *from,  /* our string argument as encoded string */
1176          *to;    /* the result as encoded string */
1177     Py_ssize_t from_length;    /* length of string */
1178     size_t to_length;          /* length of result */
1179     int encoding = -1;         /* client encoding */
1180 
1181     if (PyBytes_Check(data)) {
1182         PyBytes_AsStringAndSize(data, &from, &from_length);
1183     }
1184     else if (PyUnicode_Check(data)) {
1185         encoding = PQclientEncoding(self->cnx);
1186         tmp_obj = get_encoded_string(data, encoding);
1187         if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
1188         PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
1189     }
1190     else {
1191         PyErr_SetString(
1192             PyExc_TypeError,
1193             "Method escape_bytea() expects a string as argument");
1194         return NULL;
1195     }
1196 
1197     to = (char *) PQescapeByteaConn(self->cnx,
1198         (unsigned char *) from, (size_t) from_length, &to_length);
1199 
1200     Py_XDECREF(tmp_obj);
1201 
1202     if (encoding == -1)
1203         to_obj = PyBytes_FromStringAndSize(to, (Py_ssize_t) to_length - 1);
1204     else
1205         to_obj = get_decoded_string(to, (Py_ssize_t) to_length - 1, encoding);
1206     if (to)
1207         PQfreemem(to);
1208     return to_obj;
1209 }
1210 
1211 #ifdef LARGE_OBJECTS
1212 
1213 /* Constructor for large objects (internal use only) */
1214 static largeObject *
large_new(connObject * pgcnx,Oid oid)1215 large_new(connObject *pgcnx, Oid oid)
1216 {
1217     largeObject *large_obj;
1218 
1219     if (!(large_obj = PyObject_New(largeObject, &largeType))) {
1220         return NULL;
1221     }
1222 
1223     Py_XINCREF(pgcnx);
1224     large_obj->pgcnx = pgcnx;
1225     large_obj->lo_fd = -1;
1226     large_obj->lo_oid = oid;
1227 
1228     return large_obj;
1229 }
1230 
1231 /* Create large object. */
1232 static char conn_locreate__doc__[] =
1233 "locreate(mode) -- create a new large object in the database";
1234 
1235 static PyObject *
conn_locreate(connObject * self,PyObject * args)1236 conn_locreate(connObject *self, PyObject *args)
1237 {
1238     int mode;
1239     Oid lo_oid;
1240 
1241     /* checks validity */
1242     if (!_check_cnx_obj(self)) {
1243         return NULL;
1244     }
1245 
1246     /* gets arguments */
1247     if (!PyArg_ParseTuple(args, "i", &mode)) {
1248         PyErr_SetString(PyExc_TypeError,
1249                         "Method locreate() takes an integer argument");
1250         return NULL;
1251     }
1252 
1253     /* creates large object */
1254     lo_oid = lo_creat(self->cnx, mode);
1255     if (lo_oid == 0) {
1256         set_error_msg(OperationalError, "Can't create large object");
1257         return NULL;
1258     }
1259 
1260     return (PyObject *) large_new(self, lo_oid);
1261 }
1262 
1263 /* Init from already known oid. */
1264 static char conn_getlo__doc__[] =
1265 "getlo(oid) -- create a large object instance for the specified oid";
1266 
1267 static PyObject *
conn_getlo(connObject * self,PyObject * args)1268 conn_getlo(connObject *self, PyObject *args)
1269 {
1270     int oid;
1271     Oid lo_oid;
1272 
1273     /* checks validity */
1274     if (!_check_cnx_obj(self)) {
1275         return NULL;
1276     }
1277 
1278     /* gets arguments */
1279     if (!PyArg_ParseTuple(args, "i", &oid)) {
1280         PyErr_SetString(PyExc_TypeError,
1281                         "Method getlo() takes an integer argument");
1282         return NULL;
1283     }
1284 
1285     lo_oid = (Oid) oid;
1286     if (lo_oid == 0) {
1287         PyErr_SetString(PyExc_ValueError, "The object oid can't be null");
1288         return NULL;
1289     }
1290 
1291     /* creates object */
1292     return (PyObject *) large_new(self, lo_oid);
1293 }
1294 
1295 /* Import unix file. */
1296 static char conn_loimport__doc__[] =
1297 "loimport(name) -- create a new large object from specified file";
1298 
1299 static PyObject *
conn_loimport(connObject * self,PyObject * args)1300 conn_loimport(connObject *self, PyObject *args)
1301 {
1302     char *name;
1303     Oid lo_oid;
1304 
1305     /* checks validity */
1306     if (!_check_cnx_obj(self)) {
1307         return NULL;
1308     }
1309 
1310     /* gets arguments */
1311     if (!PyArg_ParseTuple(args, "s", &name)) {
1312         PyErr_SetString(PyExc_TypeError,
1313                         "Method loimport() takes a string argument");
1314         return NULL;
1315     }
1316 
1317     /* imports file and checks result */
1318     lo_oid = lo_import(self->cnx, name);
1319     if (lo_oid == 0) {
1320         set_error_msg(OperationalError, "Can't create large object");
1321         return NULL;
1322     }
1323 
1324     return (PyObject *) large_new(self, lo_oid);
1325 }
1326 
1327 #endif /* LARGE_OBJECTS */
1328 
1329 /* Reset connection. */
1330 static char conn_reset__doc__[] =
1331 "reset() -- reset connection with current parameters\n\n"
1332 "All derived queries and large objects derived from this connection\n"
1333 "will not be usable after this call.\n";
1334 
1335 static PyObject *
conn_reset(connObject * self,PyObject * noargs)1336 conn_reset(connObject *self, PyObject *noargs)
1337 {
1338     if (!self->cnx) {
1339         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
1340         return NULL;
1341     }
1342 
1343     /* resets the connection */
1344     PQreset(self->cnx);
1345     Py_INCREF(Py_None);
1346     return Py_None;
1347 }
1348 
1349 /* Cancel current command. */
1350 static char conn_cancel__doc__[] =
1351 "cancel() -- abandon processing of the current command";
1352 
1353 static PyObject *
conn_cancel(connObject * self,PyObject * noargs)1354 conn_cancel(connObject *self, PyObject *noargs)
1355 {
1356     if (!self->cnx) {
1357         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
1358         return NULL;
1359     }
1360 
1361     /* request that the server abandon processing of the current command */
1362     return PyInt_FromLong((long) PQrequestCancel(self->cnx));
1363 }
1364 
1365 /* Get connection socket. */
1366 static char conn_fileno__doc__[] =
1367 "fileno() -- return database connection socket file handle";
1368 
1369 static PyObject *
conn_fileno(connObject * self,PyObject * noargs)1370 conn_fileno(connObject *self, PyObject *noargs)
1371 {
1372     if (!self->cnx) {
1373         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
1374         return NULL;
1375     }
1376 
1377     return PyInt_FromLong((long) PQsocket(self->cnx));
1378 }
1379 
1380 /* Set external typecast callback function. */
1381 static char conn_set_cast_hook__doc__[] =
1382 "set_cast_hook(func) -- set a fallback typecast function";
1383 
1384 static PyObject *
conn_set_cast_hook(connObject * self,PyObject * func)1385 conn_set_cast_hook(connObject *self, PyObject *func)
1386 {
1387     PyObject *ret = NULL;
1388 
1389     if (func == Py_None) {
1390         Py_XDECREF(self->cast_hook);
1391         self->cast_hook = NULL;
1392         Py_INCREF(Py_None); ret = Py_None;
1393     }
1394     else if (PyCallable_Check(func)) {
1395         Py_XINCREF(func); Py_XDECREF(self->cast_hook);
1396         self->cast_hook = func;
1397         Py_INCREF(Py_None); ret = Py_None;
1398     }
1399     else {
1400         PyErr_SetString(PyExc_TypeError,
1401                         "Method set_cast_hook() expects"
1402                         " a callable or None as argument");
1403     }
1404 
1405     return ret;
1406 }
1407 
1408 /* Get notice receiver callback function. */
1409 static char conn_get_cast_hook__doc__[] =
1410 "get_cast_hook() -- get the fallback typecast function";
1411 
1412 static PyObject *
conn_get_cast_hook(connObject * self,PyObject * noargs)1413 conn_get_cast_hook(connObject *self, PyObject *noargs)
1414 {
1415     PyObject *ret = self->cast_hook;;
1416 
1417     if (!ret)
1418         ret = Py_None;
1419     Py_INCREF(ret);
1420 
1421     return ret;
1422 }
1423 
1424 /* Get asynchronous connection state. */
1425 static char conn_poll__doc__[] =
1426 "poll() -- Completes an asynchronous connection";
1427 
1428 static PyObject *
conn_poll(connObject * self,PyObject * args)1429 conn_poll(connObject *self, PyObject *args)
1430 {
1431     int rc;
1432 
1433     if (!self->cnx) {
1434         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
1435         return NULL;
1436     }
1437 
1438     /* check args */
1439     if (!PyArg_ParseTuple(args, "")) {
1440         PyErr_SetString(PyExc_TypeError,
1441             "method poll() takes no parameters");
1442         return NULL;
1443     }
1444 
1445     Py_BEGIN_ALLOW_THREADS
1446     rc = PQconnectPoll(self->cnx);
1447     Py_END_ALLOW_THREADS
1448 
1449     if (rc == PGRES_POLLING_FAILED) {
1450         set_error(InternalError, "Polling failed", self->cnx, NULL);
1451         Py_XDECREF(self);
1452         return NULL;
1453     }
1454 
1455     return PyInt_FromLong(rc);
1456 }
1457 
1458 /* Set notice receiver callback function. */
1459 static char conn_set_notice_receiver__doc__[] =
1460 "set_notice_receiver(func) -- set the current notice receiver";
1461 
1462 static PyObject *
conn_set_notice_receiver(connObject * self,PyObject * func)1463 conn_set_notice_receiver(connObject *self, PyObject *func)
1464 {
1465     PyObject *ret = NULL;
1466 
1467     if (func == Py_None) {
1468         Py_XDECREF(self->notice_receiver);
1469         self->notice_receiver = NULL;
1470         Py_INCREF(Py_None); ret = Py_None;
1471     }
1472     else if (PyCallable_Check(func)) {
1473         Py_XINCREF(func); Py_XDECREF(self->notice_receiver);
1474         self->notice_receiver = func;
1475         PQsetNoticeReceiver(self->cnx, notice_receiver, self);
1476         Py_INCREF(Py_None); ret = Py_None;
1477     }
1478     else {
1479         PyErr_SetString(PyExc_TypeError,
1480                         "Method set_notice_receiver() expects"
1481                         " a callable or None as argument");
1482     }
1483 
1484     return ret;
1485 }
1486 
1487 /* Get notice receiver callback function. */
1488 static char conn_get_notice_receiver__doc__[] =
1489 "get_notice_receiver() -- get the current notice receiver";
1490 
1491 static PyObject *
conn_get_notice_receiver(connObject * self,PyObject * noargs)1492 conn_get_notice_receiver(connObject *self, PyObject *noargs)
1493 {
1494     PyObject *ret = self->notice_receiver;
1495 
1496     if (!ret)
1497         ret = Py_None;
1498     Py_INCREF(ret);
1499 
1500     return ret;
1501 }
1502 
1503 /* Close without deleting. */
1504 static char conn_close__doc__[] =
1505 "close() -- close connection\n\n"
1506 "All instances of the connection object and derived objects\n"
1507 "(queries and large objects) can no longer be used after this call.\n";
1508 
1509 static PyObject *
conn_close(connObject * self,PyObject * noargs)1510 conn_close(connObject *self, PyObject *noargs)
1511 {
1512     /* connection object cannot already be closed */
1513     if (!self->cnx) {
1514         set_error_msg(InternalError, "Connection already closed");
1515         return NULL;
1516     }
1517 
1518     Py_BEGIN_ALLOW_THREADS
1519     PQfinish(self->cnx);
1520     Py_END_ALLOW_THREADS
1521 
1522     self->cnx = NULL;
1523     Py_INCREF(Py_None);
1524     return Py_None;
1525 }
1526 
1527 /* Get asynchronous notify. */
1528 static char conn_get_notify__doc__[] =
1529 "getnotify() -- get database notify for this connection";
1530 
1531 static PyObject *
conn_get_notify(connObject * self,PyObject * noargs)1532 conn_get_notify(connObject *self, PyObject *noargs)
1533 {
1534     PGnotify *notify;
1535 
1536     if (!self->cnx) {
1537         PyErr_SetString(PyExc_TypeError, "Connection is not valid");
1538         return NULL;
1539     }
1540 
1541     /* checks for NOTIFY messages */
1542     PQconsumeInput(self->cnx);
1543 
1544     if (!(notify = PQnotifies(self->cnx))) {
1545         Py_INCREF(Py_None);
1546         return Py_None;
1547     }
1548     else {
1549         PyObject *notify_result, *tmp;
1550 
1551         if (!(tmp = PyStr_FromString(notify->relname))) {
1552             return NULL;
1553         }
1554 
1555         if (!(notify_result = PyTuple_New(3))) {
1556             return NULL;
1557         }
1558 
1559         PyTuple_SET_ITEM(notify_result, 0, tmp);
1560 
1561         if (!(tmp = PyInt_FromLong(notify->be_pid))) {
1562             Py_DECREF(notify_result);
1563             return NULL;
1564         }
1565 
1566         PyTuple_SET_ITEM(notify_result, 1, tmp);
1567 
1568         /* extra exists even in old versions that did not support it */
1569         if (!(tmp = PyStr_FromString(notify->extra))) {
1570             Py_DECREF(notify_result);
1571             return NULL;
1572         }
1573 
1574         PyTuple_SET_ITEM(notify_result, 2, tmp);
1575 
1576         PQfreemem(notify);
1577 
1578         return notify_result;
1579     }
1580 }
1581 
1582 /* Get the list of connection attributes. */
1583 static PyObject *
conn_dir(connObject * self,PyObject * noargs)1584 conn_dir(connObject *self, PyObject *noargs)
1585 {
1586     PyObject *attrs;
1587 
1588     attrs = PyObject_Dir(PyObject_Type((PyObject *) self));
1589     PyObject_CallMethod(
1590         attrs, "extend", "[sssssssssssss]",
1591         "host", "port", "db", "options", "error", "status", "user",
1592         "protocol_version", "server_version", "socket", "backend_pid",
1593         "ssl_in_use", "ssl_attributes");
1594 
1595     return attrs;
1596 }
1597 
1598 /* Connection object methods */
1599 static struct PyMethodDef conn_methods[] = {
1600     {"__dir__", (PyCFunction) conn_dir,  METH_NOARGS, NULL},
1601 
1602     {"source", (PyCFunction) conn_source,
1603         METH_NOARGS, conn_source__doc__},
1604     {"query", (PyCFunction) conn_query,
1605         METH_VARARGS, conn_query__doc__},
1606     {"send_query", (PyCFunction) conn_send_query,
1607         METH_VARARGS, conn_send_query__doc__},
1608     {"query_prepared", (PyCFunction) conn_query_prepared,
1609         METH_VARARGS, conn_query_prepared__doc__},
1610     {"prepare", (PyCFunction) conn_prepare,
1611         METH_VARARGS, conn_prepare__doc__},
1612     {"describe_prepared", (PyCFunction) conn_describe_prepared,
1613         METH_VARARGS, conn_describe_prepared__doc__},
1614     {"poll", (PyCFunction) conn_poll,
1615         METH_VARARGS, conn_poll__doc__},
1616     {"reset", (PyCFunction) conn_reset,
1617         METH_NOARGS, conn_reset__doc__},
1618     {"cancel", (PyCFunction) conn_cancel,
1619         METH_NOARGS, conn_cancel__doc__},
1620     {"close", (PyCFunction) conn_close,
1621         METH_NOARGS, conn_close__doc__},
1622     {"fileno", (PyCFunction) conn_fileno,
1623         METH_NOARGS, conn_fileno__doc__},
1624     {"get_cast_hook", (PyCFunction) conn_get_cast_hook,
1625         METH_NOARGS, conn_get_cast_hook__doc__},
1626     {"set_cast_hook", (PyCFunction) conn_set_cast_hook,
1627         METH_O, conn_set_cast_hook__doc__},
1628     {"get_notice_receiver", (PyCFunction) conn_get_notice_receiver,
1629         METH_NOARGS, conn_get_notice_receiver__doc__},
1630     {"set_notice_receiver", (PyCFunction) conn_set_notice_receiver,
1631         METH_O, conn_set_notice_receiver__doc__},
1632     {"getnotify", (PyCFunction) conn_get_notify,
1633         METH_NOARGS, conn_get_notify__doc__},
1634     {"inserttable", (PyCFunction) conn_inserttable,
1635         METH_VARARGS, conn_inserttable__doc__},
1636     {"transaction", (PyCFunction) conn_transaction,
1637         METH_NOARGS, conn_transaction__doc__},
1638     {"parameter", (PyCFunction) conn_parameter,
1639         METH_VARARGS, conn_parameter__doc__},
1640     {"date_format", (PyCFunction) conn_date_format,
1641         METH_NOARGS, conn_date_format__doc__},
1642 
1643 #ifdef ESCAPING_FUNCS
1644     {"escape_literal", (PyCFunction) conn_escape_literal,
1645         METH_O, conn_escape_literal__doc__},
1646     {"escape_identifier", (PyCFunction) conn_escape_identifier,
1647         METH_O, conn_escape_identifier__doc__},
1648 #endif /* ESCAPING_FUNCS */
1649     {"escape_string", (PyCFunction) conn_escape_string,
1650         METH_O, conn_escape_string__doc__},
1651     {"escape_bytea", (PyCFunction) conn_escape_bytea,
1652         METH_O, conn_escape_bytea__doc__},
1653 
1654 #ifdef DIRECT_ACCESS
1655     {"putline", (PyCFunction) conn_putline,
1656         METH_VARARGS, conn_putline__doc__},
1657     {"getline", (PyCFunction) conn_getline,
1658         METH_NOARGS, conn_getline__doc__},
1659     {"endcopy", (PyCFunction) conn_endcopy,
1660         METH_NOARGS, conn_endcopy__doc__},
1661     {"set_non_blocking", (PyCFunction) conn_set_non_blocking,
1662         METH_O, conn_set_non_blocking__doc__},
1663     {"is_non_blocking", (PyCFunction) conn_is_non_blocking,
1664         METH_NOARGS, conn_is_non_blocking__doc__},
1665 #endif /* DIRECT_ACCESS */
1666 
1667 #ifdef LARGE_OBJECTS
1668     {"locreate", (PyCFunction) conn_locreate,
1669         METH_VARARGS, conn_locreate__doc__},
1670     {"getlo", (PyCFunction) conn_getlo,
1671         METH_VARARGS, conn_getlo__doc__},
1672     {"loimport", (PyCFunction) conn_loimport,
1673         METH_VARARGS, conn_loimport__doc__},
1674 #endif /* LARGE_OBJECTS */
1675 
1676     {NULL, NULL} /* sentinel */
1677 };
1678 
1679 static char conn__doc__[] = "PostgreSQL connection object";
1680 
1681 /* Connection type definition */
1682 static PyTypeObject connType = {
1683     PyVarObject_HEAD_INIT(NULL, 0)
1684     "pg.Connection",              /* tp_name */
1685     sizeof(connObject),           /* tp_basicsize */
1686     0,                            /* tp_itemsize */
1687     (destructor) conn_dealloc,    /* tp_dealloc */
1688     0,                            /* tp_print */
1689     0,                            /* tp_getattr */
1690     0,                            /* tp_setattr */
1691     0,                            /* tp_reserved */
1692     0,                            /* tp_repr */
1693     0,                            /* tp_as_number */
1694     0,                            /* tp_as_sequence */
1695     0,                            /* tp_as_mapping */
1696     0,                            /* tp_hash */
1697     0,                            /* tp_call */
1698     0,                            /* tp_str */
1699     (getattrofunc) conn_getattr,  /* tp_getattro */
1700     0,                            /* tp_setattro */
1701     0,                            /* tp_as_buffer */
1702     Py_TPFLAGS_DEFAULT,           /* tp_flags */
1703     conn__doc__,                  /* tp_doc */
1704     0,                            /* tp_traverse */
1705     0,                            /* tp_clear */
1706     0,                            /* tp_richcompare */
1707     0,                            /* tp_weaklistoffset */
1708     0,                            /* tp_iter */
1709     0,                            /* tp_iternext */
1710     conn_methods,                 /* tp_methods */
1711 };
1712