@@ -336,6 +336,71 @@ def testCursorReadInXact(self):
336336 with self .db .xact ():
337337 self .testCursorRead ()
338338
339+ def testWithScroll (self ):
340+ # Use a large row-set.
341+ imin = 0
342+ imax = 2 ** 16 - 1
343+ ps = self .db .prepare ("SELECT i FROM generate_series(0, (2^16)::int) AS g(i)" )
344+ c = ps (with_scroll = True )
345+
346+ self .failUnlessEqual ([x for x , in c .read (10 )], list (range (10 )))
347+ # bit strange to me, but i've watched the fetch backwards -jwp 2009
348+ self .failUnlessEqual ([x for x , in c .read (- 10 )], list (range (8 , - 1 , - 1 )))
349+ c .seek (0 , 2 )
350+ self .failUnlessEqual ([x for x , in c .read (- 10 )], list (range (imax , imax - 10 , - 1 )))
351+
352+ # move to end
353+ c .seek (0 , 2 )
354+ self .failUnlessEqual ([x for x , in c .read (- 100 )], list (range (imax , imax - 100 , - 1 )))
355+ # move backwards, relative
356+ c .seek (- 100 , 1 )
357+ self .failUnlessEqual ([x for x , in c .read (- 100 )], list (range (imax - 200 , imax - 300 , - 1 )))
358+
359+ # move abs, again
360+ c .seek (14000 )
361+ self .failUnlessEqual ([x for x , in c .read (100 )], list (range (14000 , 14100 )))
362+ # move forwards, relative
363+ c .seek (100 , 1 )
364+ self .failUnlessEqual ([x for x , in c .read (100 )], list (range (14200 , 14300 )))
365+ # move abs, again
366+ c .seek (24000 )
367+ self .failUnlessEqual ([x for x , in c .read (200 )], list (range (24000 , 24200 )))
368+ # move to end and then back some
369+ c .seek (20 , 2 )
370+ self .failUnlessEqual ([x for x , in c .read (- 200 )], list (range (imax - 20 , imax - 20 - 200 , - 1 )))
371+
372+ c .seek (0 , 2 )
373+ c .seek (- 10 , 1 )
374+ r1 = c .read (10 )
375+ c .seek (10 , 2 )
376+ self .failUnlessEqual (r1 , c .read (10 ))
377+
378+ def testWithHold (self ):
379+ with self .db .xact ():
380+ ps = self .db .prepare ("SELECT 1" )
381+ c = ps (with_hold = True )
382+ cid = c .cursor_id
383+ self .failUnlessEqual (c .read ()[0 ][0 ], 1 )
384+ # make sure it's not cheating
385+ self .failUnlessEqual (c .cursor_id , cid )
386+ # check grabs beyond the default chunksize.
387+ with self .db .xact ():
388+ ps = self .db .prepare ("SELECT i FROM generate_series(0, 99) as g(i)" )
389+ c = ps (with_hold = True )
390+ cid = c .cursor_id
391+ self .failUnlessEqual ([x for x , in c .read ()], list (range (100 )))
392+ # make sure it's not cheating
393+ self .failUnlessEqual (c .cursor_id , cid )
394+
395+ def testNoHold (self ):
396+ with self .db .xact ():
397+ c = self .db .prepare ("SELECT i from generate_series(0, 99) as g(i)" )()
398+ # no hold, no cursor after xact.
399+ self .failUnlessRaises (
400+ pg_exc .CursorNameError ,
401+ c .read
402+ )
403+
339404 def testChunking (self ):
340405 gs = self .db .prepare ("SELECT i FROM generate_series(1, 10000) AS g(i)" )
341406 self .failUnlessEqual (
@@ -355,7 +420,7 @@ def testChunking(self):
355420 read_chunking = self .db .prepare ('select * FROM chunking' )
356421 write_chunking = db2 .prepare ('insert into chunking values ($1, $2)' )
357422 out = read_chunking ()
358- out .chunksize = 256
423+ out .chunksize = 512
359424 for rows in out .chunks :
360425 write_chunking .load (rows )
361426 self .failUnlessEqual (
@@ -368,10 +433,15 @@ def testChunking(self):
368433 )
369434 finally :
370435 try :
371- self .db .execute ('DROP TABLE chunking' )
436+ with self .db .xact ():
437+ self .db .execute ('DROP TABLE chunking' )
372438 except :
373439 pass
374440
441+ def testChunkingInXact (self ):
442+ with self .db .xact ():
443+ self .testChunking ()
444+
375445 def testDDL (self ):
376446 self .db .execute ("CREATE TEMP TABLE t(i int)" )
377447 try :
0 commit comments