~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/canonical/database/postgresql.py

  • Committer: Julian Edwards
  • Date: 2011-07-28 20:46:18 UTC
  • mfrom: (13553 devel)
  • mto: This revision was merged to the branch mainline in revision 13555.
  • Revision ID: julian.edwards@canonical.com-20110728204618-tivj2wx2oa9s32bx
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
 
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
3
 
4
4
"""
10
10
 
11
11
import re
12
12
 
13
 
from canonical.database.sqlbase import (
14
 
    quote,
15
 
    quoteIdentifier,
16
 
    sqlvalues,
17
 
    )
 
13
from canonical.database.sqlbase import quote, quoteIdentifier, sqlvalues
18
14
 
19
15
 
20
16
def listReferences(cur, table, column, _state=None):
89
85
 
90
86
    for t in cur.fetchall():
91
87
        # t == (src_table, src_column, dest_table, dest_column, upd, del)
92
 
        # Avoid loops:
93
 
        if t not in _state:
 
88
        if t not in _state: # Avoid loops
94
89
            _state.append(t)
95
90
            # Recurse, Locating references to the reference we just found.
96
91
            listReferences(cur, t[0], t[1], _state)
98
93
    # from the original (table, column), making it easier to change keys
99
94
    return _state
100
95
 
101
 
 
102
96
def listUniques(cur, table, column):
103
97
    '''Return a list of unique indexes on `table` that include the `column`
104
98
 
181
175
            rv.append(tuple(keys))
182
176
    return rv
183
177
 
184
 
 
185
178
def listSequences(cur):
186
179
    """Return a list of (schema, sequence, table, column) tuples.
187
180
 
213
206
    for schema, sequence in list(cur.fetchall()):
214
207
        match = re.search('^(\w+)_(\w+)_seq$', sequence)
215
208
        if match is None:
216
 
            rv.append((schema, sequence, None, None))
 
209
            rv.append( (schema, sequence, None, None) )
217
210
        else:
218
211
            table = match.group(1)
219
212
            column = match.group(2)
232
225
            cur.execute(sql, dict(schema=schema, table=table, column=column))
233
226
            num = cur.fetchone()[0]
234
227
            if num == 1:
235
 
                rv.append((schema, sequence, table, column))
 
228
                rv.append( (schema, sequence, table, column) )
236
229
            else:
237
 
                rv.append((schema, sequence, None, None))
 
230
                rv.append( (schema, sequence, None, None) )
238
231
    return rv
239
232
 
240
 
 
241
233
def generateResetSequencesSQL(cur):
242
234
    """Return SQL that will reset table sequences to match the data in them.
243
235
    """
265
257
    else:
266
258
        return ''
267
259
 
268
 
 
269
260
def resetSequences(cur):
270
261
    """Reset table sequences to match the data in them.
271
262
 
290
281
# Regular expression used to parse row count estimate from EXPLAIN output
291
282
_rows_re = re.compile("rows=(\d+)\swidth=")
292
283
 
293
 
 
294
284
def estimateRowCount(cur, query):
295
285
    """Ask the PostgreSQL query optimizer for an estimated rowcount.
296
286
 
432
422
 
433
423
    cur.execute("SET enable_seqscan=%s" % permission_value)
434
424
 
435
 
 
436
425
def all_tables_in_schema(cur, schema):
437
426
    """Return a set of all tables in the given schema.
438
 
 
 
427
   
439
428
    :returns: A set of quoted, fully qualified table names.
440
429
    """
441
430
    cur.execute("""
493
482
    need the components seperated out (such as pg_dump command line
494
483
    arguments). This class allows you to switch easily between formats.
495
484
 
496
 
    Quoted or escaped values are not supported.
497
 
 
498
485
    >>> cs = ConnectionString('user=foo dbname=launchpad_dev')
499
486
    >>> cs.dbname
500
487
    'launchpad_dev'
509
496
        'dbname', 'user', 'host', 'port', 'connect_timeout', 'sslmode']
510
497
 
511
498
    def __init__(self, conn_str):
512
 
        if "'" in conn_str or "\\" in conn_str:
513
 
            raise AssertionError("quoted or escaped values are not supported")
514
 
 
515
499
        if '=' not in conn_str:
516
500
            # Just a dbname
517
501
            for key in self.CONNECTION_KEYS:
523
507
            # be added after construction or not actually required
524
508
            # at all in some instances.
525
509
            for key in self.CONNECTION_KEYS:
526
 
                match = re.search(r'%s=([^ ]+)' % key, conn_str)
 
510
                match = re.search(r'%s=(\w+)' % key, conn_str)
527
511
                if match is None:
528
512
                    setattr(self, key, None)
529
513
                else:
585
569
 
586
570
    for table, column in listReferences(cur, 'person', 'id'):
587
571
        print '%32s %32s' % (table, column)
 
572