summaryrefslogtreecommitdiff
path: root/sqlplain/pager.py
blob: 13ba1f141548105318c42e2cb234fe5a5e8cd95f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import string

def _fetchpage_mssql(self, pageno, maxrows, query_args):
    query_templ = self.query_templ
    nrows, npages = self._rows_pages(maxrows, query_templ, query_args)
    n_end = max(nrows -  pageno * maxrows, 0)
    ofields = self.ofields
    templ = string.Template('''
    SELECT TOP ${maxrows} * FROM
    (SELECT TOP ${n_end} * FROM
    ($query_templ) AS T1
    ORDER BY ${ofields} DESC) AS T2
    ORDER BY ${ofields} ASC
    ''').substitute(locals())
    res = self.conn.execute(templ, query_args)
    res.nrows = nrows
    res.npages = npages
    return res

def _fetchpage(self, pageno, maxrows, query_args):
    query_templ = self.query_templ    
    currentrow = pageno * maxrows
    ofields = self.ofields
    templ = string.Template('''
    SELECT * FROM ($query_templ) AS tmp
    ORDER BY ${ofields} LIMIT ${maxrows} OFFSET ${currentrow}
    ''').substitute(locals())
    res = self.conn.execute(templ, query_args)
    res.nrows, res.npages = self._rows_pages(maxrows, query_templ, query_args) 
    return res

class SqlPaginator(object):        
    def __init__(self, conn, query_templ, ofields, query_args=()):
        self.conn = conn
        self.query_templ = query_templ
        self.query_args = query_args
        self.ofields = ofields
        if conn.dbtype == 'mssql':
            self._fetchpage = _fetchpage_mssql.__get__(self)
        else:
            self._fetchpage = _fetchpage.__get__(self)

    def _rows_pages(self, maxrows, query_templ, query_args):
        "Count the rows and pages returned by the query"
        ct = 'SELECT count(*) FROM (%s) AS t' % query_templ
        nrows = self.conn.execute(ct, query_args, scalar=True) 
        npages, rest = divmod(nrows, maxrows)    
        if rest:
            npages += 1
        return nrows, npages

    def fetchpage(self, pageno, maxrows, query_args=None):
        """
        Fetch a page from a paginated query. Return a list with attributes
        nrows and npages.
        """
        pageno = max(0, pageno) # makes sure pageno is positive
        if query_args is None:
            query_args = self.query_args
        return self._fetchpage(pageno, maxrows, query_args)

'''
Notice: in SQL Server 2005 there is the row_number() function which can
be used in conjunction with ORDER BY; an example is the following:
select * from
(select Row_number() over (order by csfb_issuer_id) as rn,* 
 from csfbcreditdefaultswaps) as x  
where rn between 100 and 110

'''