mirror of
				https://github.com/psycopg/psycopg2.git
				synced 2025-10-31 15:57:31 +03:00 
			
		
		
		
	First try at curs.withhold implementation
This commit is contained in:
		
							parent
							
								
									cb1d163f4f
								
							
						
					
					
						commit
						2f6336ea78
					
				|  | @ -42,6 +42,7 @@ struct cursorObject { | ||||||
| 
 | 
 | ||||||
|     int closed:1;            /* 1 if the cursor is closed */ |     int closed:1;            /* 1 if the cursor is closed */ | ||||||
|     int notuples:1;          /* 1 if the command was not a SELECT query */ |     int notuples:1;          /* 1 if the command was not a SELECT query */ | ||||||
|  |     int withhold:1;          /* 1 if the cursor is named and uses WITH HOLD */ | ||||||
| 
 | 
 | ||||||
|     long int rowcount;       /* number of rows affected by last execute */ |     long int rowcount;       /* number of rows affected by last execute */ | ||||||
|     long int columns;        /* number of columns fetched from the db */ |     long int columns;        /* number of columns fetched from the db */ | ||||||
|  | @ -99,7 +100,7 @@ if ((self)->notuples && (self)->name == NULL) {               \ | ||||||
|     return NULL; } |     return NULL; } | ||||||
| 
 | 
 | ||||||
| #define EXC_IF_NO_MARK(self) \ | #define EXC_IF_NO_MARK(self) \ | ||||||
| if ((self)->mark != (self)->conn->mark) {                                  \ | if ((self)->mark != (self)->conn->mark && (self)->withhold == 0) {                                  \ | ||||||
|     PyErr_SetString(ProgrammingError, "named cursor isn't valid anymore"); \ |     PyErr_SetString(ProgrammingError, "named cursor isn't valid anymore"); \ | ||||||
|     return NULL; } |     return NULL; } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -391,8 +391,10 @@ _psyco_curs_execute(cursorObject *self, | ||||||
| 
 | 
 | ||||||
|         if (self->name != NULL) { |         if (self->name != NULL) { | ||||||
|             self->query = Bytes_FromFormat( |             self->query = Bytes_FromFormat( | ||||||
|                 "DECLARE \"%s\" CURSOR WITHOUT HOLD FOR %s", |                 "DECLARE \"%s\" CURSOR %s HOLD FOR %s", | ||||||
|                 self->name, Bytes_AS_STRING(fquery)); |                 self->name, | ||||||
|  |                 self->withhold ? "WITH" : "WITHOUT", | ||||||
|  |                 Bytes_AS_STRING(fquery)); | ||||||
|             Py_DECREF(fquery); |             Py_DECREF(fquery); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|  | @ -402,8 +404,10 @@ _psyco_curs_execute(cursorObject *self, | ||||||
|     else { |     else { | ||||||
|         if (self->name != NULL) { |         if (self->name != NULL) { | ||||||
|             self->query = Bytes_FromFormat( |             self->query = Bytes_FromFormat( | ||||||
|                 "DECLARE \"%s\" CURSOR WITHOUT HOLD FOR %s", |                 "DECLARE \"%s\" CURSOR %s HOLD FOR %s", | ||||||
|                 self->name, Bytes_AS_STRING(operation)); |                 self->name, | ||||||
|  |                 self->withhold ? "WITH" : "WITHOUT", | ||||||
|  |                 Bytes_AS_STRING(operation)); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             /* Transfer reference ownership of the str in operation to
 |             /* Transfer reference ownership of the str in operation to
 | ||||||
|  | @ -461,11 +465,7 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs) | ||||||
|                 "can't use a named cursor outside of transactions", NULL, NULL); |                 "can't use a named cursor outside of transactions", NULL, NULL); | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|         if (self->conn->mark != self->mark) { |         EXC_IF_NO_MARK(self); | ||||||
|             psyco_set_error(ProgrammingError, self, |  | ||||||
|                 "named cursor isn't valid anymore", NULL, NULL); |  | ||||||
|             return NULL; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     EXC_IF_CURS_CLOSED(self); |     EXC_IF_CURS_CLOSED(self); | ||||||
|  | @ -1519,7 +1519,7 @@ exit: | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* extension: closed - return true if cursor is closed*/ | /* extension: closed - return true if cursor is closed */ | ||||||
| 
 | 
 | ||||||
| #define psyco_curs_closed_doc \ | #define psyco_curs_closed_doc \ | ||||||
| "True if cursor is closed, False if cursor is open" | "True if cursor is closed, False if cursor is open" | ||||||
|  | @ -1535,6 +1535,39 @@ psyco_curs_get_closed(cursorObject *self, void *closure) | ||||||
|     return closed; |     return closed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* extension: withhold - get or set "WITH HOLD" for named cursors */ | ||||||
|  | 
 | ||||||
|  | #define psyco_curs_withhold_doc \ | ||||||
|  | "Set or return cursor use of WITH HOLD" | ||||||
|  | 
 | ||||||
|  | static PyObject * | ||||||
|  | psyco_curs_withhold_get(cursorObject *self) | ||||||
|  | { | ||||||
|  |     PyObject *ret; | ||||||
|  |     ret = self->withhold ? Py_True : Py_False; | ||||||
|  |     Py_INCREF(ret); | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | psyco_curs_withhold_set(cursorObject *self, PyObject *pyvalue) | ||||||
|  | { | ||||||
|  |     int value; | ||||||
|  | 
 | ||||||
|  |     if (self->name == NULL) { | ||||||
|  |         PyErr_SetString(ProgrammingError, | ||||||
|  |             "trying to set .withhold on unnamed cursor"); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     if ((value = PyObject_IsTrue(pyvalue)) == -1)  | ||||||
|  |         return -1; | ||||||
|  | 
 | ||||||
|  |     self->withhold = value; | ||||||
|  |      | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1657,6 +1690,10 @@ static struct PyGetSetDef cursorObject_getsets[] = { | ||||||
| #ifdef PSYCOPG_EXTENSIONS | #ifdef PSYCOPG_EXTENSIONS | ||||||
|     { "closed", (getter)psyco_curs_get_closed, NULL, |     { "closed", (getter)psyco_curs_get_closed, NULL, | ||||||
|       psyco_curs_closed_doc, NULL }, |       psyco_curs_closed_doc, NULL }, | ||||||
|  |     { "withhold", | ||||||
|  |       (getter)psyco_curs_withhold_get, | ||||||
|  |       (setter)psyco_curs_withhold_set, | ||||||
|  |       psyco_curs_withhold_doc, NULL }, | ||||||
| #endif | #endif | ||||||
|     {NULL} |     {NULL} | ||||||
| }; | }; | ||||||
|  | @ -1686,6 +1723,7 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name) | ||||||
|     self->conn = conn; |     self->conn = conn; | ||||||
| 
 | 
 | ||||||
|     self->closed = 0; |     self->closed = 0; | ||||||
|  |     self->withhold = 0; | ||||||
|     self->mark = conn->mark; |     self->mark = conn->mark; | ||||||
|     self->pgres = NULL; |     self->pgres = NULL; | ||||||
|     self->notuples = 1; |     self->notuples = 1; | ||||||
|  |  | ||||||
|  | @ -202,6 +202,9 @@ | ||||||
|     <None Include="tests\dbapi20_tpc.py" /> |     <None Include="tests\dbapi20_tpc.py" /> | ||||||
|     <None Include="tests\test_cursor.py" /> |     <None Include="tests\test_cursor.py" /> | ||||||
|     <None Include="NEWS" /> |     <None Include="NEWS" /> | ||||||
|  |     <None Include="tests\test_cancel.py" /> | ||||||
|  |     <None Include="tests\testconfig.py" /> | ||||||
|  |     <None Include="tests\testutils.py" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Compile Include="psycopg\adapter_asis.c" /> |     <Compile Include="psycopg\adapter_asis.c" /> | ||||||
|  |  | ||||||
|  | @ -158,6 +158,27 @@ class CursorTests(unittest.TestCase): | ||||||
|         curs.execute("select data from invname order by data") |         curs.execute("select data from invname order by data") | ||||||
|         self.assertEqual(curs.fetchall(), [(10,), (20,), (30,)]) |         self.assertEqual(curs.fetchall(), [(10,), (20,), (30,)]) | ||||||
|          |          | ||||||
|  |     def test_withhold(self): | ||||||
|  |         curs = self.conn.cursor() | ||||||
|  |         curs.execute("drop table if exists withhold") | ||||||
|  |         curs.execute("create table withhold (data int)") | ||||||
|  |         for i in (10, 20, 30): | ||||||
|  |             curs.execute("insert into withhold values (%s)", (i,)) | ||||||
|  |         curs.close() | ||||||
|  | 
 | ||||||
|  |         curs = self.conn.cursor("W") | ||||||
|  |         self.assertEqual(curs.withhold, False); | ||||||
|  |         curs.withhold = True | ||||||
|  |         self.assertEqual(curs.withhold, True); | ||||||
|  |         curs.execute("select data from withhold order by data") | ||||||
|  |         self.conn.commit() | ||||||
|  |         self.assertEqual(curs.fetchall(), [(10,), (20,), (30,)]) | ||||||
|  |          | ||||||
|  |         curs = self.conn.cursor() | ||||||
|  |         curs.execute("drop table withhold") | ||||||
|  |         self.conn.commit() | ||||||
|  |          | ||||||
|  | 
 | ||||||
|     @skip_before_postgres(8, 2) |     @skip_before_postgres(8, 2) | ||||||
|     def test_iter_named_cursor_efficient(self): |     def test_iter_named_cursor_efficient(self): | ||||||
|         curs = self.conn.cursor('tmp') |         curs = self.conn.cursor('tmp') | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user