1 /* cursor.h - definition for the psycopg cursor type
2  *
3  * Copyright (C) 2003-2019 Federico Di Gregorio <fog@debian.org>
4  * Copyright (C) 2020-2021 The Psycopg Team
5  *
6  * This file is part of psycopg.
7  *
8  * psycopg2 is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published
10  * by the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * In addition, as a special exception, the copyright holders give
14  * permission to link this program with the OpenSSL library (or with
15  * modified versions of OpenSSL that use the same license as OpenSSL),
16  * and distribute linked combinations including the two.
17  *
18  * You must obey the GNU Lesser General Public License in all respects for
19  * all of the code used other than OpenSSL.
20  *
21  * psycopg2 is distributed in the hope that it will be useful, but WITHOUT
22  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
24  * License for more details.
25  */
26 
27 #ifndef PSYCOPG_CURSOR_H
28 #define PSYCOPG_CURSOR_H 1
29 
30 #include "psycopg/connection.h"
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 extern HIDDEN PyTypeObject cursorType;
37 
38 /* the typedef is forward-declared in psycopg.h */
39 struct cursorObject {
40     PyObject_HEAD
41 
42     connectionObject *conn; /* connection owning the cursor */
43 
44     int closed:1;            /* 1 if the cursor is closed */
45     int notuples:1;          /* 1 if the command was not a SELECT query */
46     int withhold:1;          /* 1 if the cursor is named and uses WITH HOLD */
47 
48     int scrollable;          /* 1 if the cursor is named and SCROLLABLE,
49                                 0 if not scrollable
50                                -1 if undefined (PG may decide scrollable or not)
51                               */
52 
53     long int rowcount;       /* number of rows affected by last execute */
54     long int columns;        /* number of columns fetched from the db */
55     long int arraysize;      /* how many rows should fetchmany() return */
56     long int itersize;       /* how many rows should iter(cur) fetch in named cursors */
57     long int row;            /* the row counter for fetch*() operations */
58     long int mark;           /* transaction marker, copied from conn */
59 
60     PyObject *description;   /* read-only attribute: sequence of 7-item
61                                 sequences.*/
62 
63     /* postgres connection stuff */
64     PGresult   *pgres;     /* result of last query */
65     PyObject   *pgstatus;  /* last message from the server after an execute */
66     Oid         lastoid;   /* last oid from an insert or InvalidOid */
67 
68     PyObject *casts;       /* an array (tuple) of typecast functions */
69     PyObject *caster;      /* the current typecaster object */
70 
71     PyObject  *copyfile;   /* file-like used during COPY TO/FROM ops */
72     Py_ssize_t copysize;   /* size of the copy buffer during COPY TO/FROM ops */
73 #define DEFAULT_COPYSIZE 16384
74 #define DEFAULT_COPYBUFF  8192
75 
76     PyObject *tuple_factory;    /* factory for result tuples */
77     PyObject *tzinfo_factory;   /* factory for tzinfo objects */
78 
79     PyObject *query;      /* last query executed */
80 
81     char *qattr;          /* quoting attr, used when quoting strings */
82     char *notice;         /* a notice from the backend */
83     char *name;           /* this cursor name */
84     char *qname;          /* this cursor name, quoted */
85 
86     PyObject *string_types;   /* a set of typecasters for string types */
87     PyObject *binary_types;   /* a set of typecasters for binary types */
88 
89     PyObject *weakreflist;    /* list of weak references */
90 
91 };
92 
93 
94 /* C-callable functions in cursor_int.c and cursor_type.c */
95 BORROWED HIDDEN PyObject *curs_get_cast(cursorObject *self, PyObject *oid);
96 HIDDEN void curs_reset(cursorObject *self);
97 RAISES_NEG HIDDEN int curs_withhold_set(cursorObject *self, PyObject *pyvalue);
98 RAISES_NEG HIDDEN int curs_scrollable_set(cursorObject *self, PyObject *pyvalue);
99 HIDDEN PyObject *curs_validate_sql_basic(cursorObject *self, PyObject *sql);
100 HIDDEN void curs_set_result(cursorObject *self, PGresult *pgres);
101 
102 /* exception-raising macros */
103 #define EXC_IF_CURS_CLOSED(self) \
104 do { \
105     if (!(self)->conn) { \
106         PyErr_SetString(InterfaceError, "the cursor has no connection"); \
107         return NULL; } \
108     if ((self)->closed || (self)->conn->closed) { \
109         PyErr_SetString(InterfaceError, "cursor already closed"); \
110         return NULL; } \
111 } while (0)
112 
113 #define EXC_IF_NO_TUPLES(self) \
114 do \
115     if ((self)->notuples && (self)->name == NULL) { \
116         PyErr_SetString(ProgrammingError, "no results to fetch"); \
117         return NULL; } \
118 while (0)
119 
120 #define EXC_IF_NO_MARK(self) \
121 do \
122     if ((self)->mark != (self)->conn->mark && (self)->withhold == 0) { \
123         PyErr_SetString(ProgrammingError, "named cursor isn't valid anymore"); \
124         return NULL; } \
125 while (0)
126 
127 #define EXC_IF_CURS_ASYNC(self, cmd) \
128 do \
129     if ((self)->conn->async == 1) { \
130         PyErr_SetString(ProgrammingError, \
131             #cmd " cannot be used in asynchronous mode"); \
132         return NULL; } \
133 while (0)
134 
135 #define EXC_IF_ASYNC_IN_PROGRESS(self, cmd) \
136 do \
137     if ((self)->conn->async_cursor != NULL) { \
138         PyErr_SetString(ProgrammingError, \
139             #cmd " cannot be used while an asynchronous query is underway"); \
140     return NULL; } \
141 while (0)
142 
143 #ifdef __cplusplus
144 }
145 #endif
146 
147 #endif /* !defined(PSYCOPG_CURSOR_H) */
148