~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to database/schema/fti.py

  • Committer: Stuart Bishop
  • Date: 2011-09-28 12:49:24 UTC
  • mfrom: (9893.10.1 trivial)
  • mto: This revision was merged to the branch mainline in revision 14178.
  • Revision ID: stuart.bishop@canonical.com-20110928124924-m5a22fymqghw6c5i
Merged trivial into distinct-db-users.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/python -S
2
2
#
3
 
# Copyright 2009 Canonical Ltd.  This software is licensed under the
 
3
# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
4
4
# GNU Affero General Public License version 3 (see the file LICENSE).
5
5
#
6
6
# This modules uses relative imports.
11
11
"""
12
12
__metaclass__ = type
13
13
 
14
 
import _pythonpath
15
 
 
16
14
from distutils.version import LooseVersion
 
15
from optparse import OptionParser
17
16
import os.path
18
 
from optparse import OptionParser
19
17
import subprocess
20
18
import sys
21
19
from tempfile import NamedTemporaryFile
22
20
from textwrap import dedent
23
21
import time
24
22
 
 
23
import _pythonpath
25
24
import psycopg2.extensions
 
25
import replication.helpers
26
26
 
27
27
from canonical.config import config
28
28
from canonical.database.postgresql import ConnectionString
29
29
from canonical.database.sqlbase import (
30
 
    connect, ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED,
31
 
    quote, quote_identifier)
32
 
from canonical.launchpad.scripts import logger, logger_options, db_options
33
 
 
34
 
import replication.helpers
 
30
    connect,
 
31
    ISOLATION_LEVEL_AUTOCOMMIT,
 
32
    ISOLATION_LEVEL_READ_COMMITTED,
 
33
    quote,
 
34
    quote_identifier,
 
35
    )
 
36
from canonical.launchpad.scripts import (
 
37
    db_options,
 
38
    logger,
 
39
    logger_options,
 
40
    )
35
41
 
36
42
# Defines parser and locale to use.
37
43
DEFAULT_CONFIG = 'default'
38
44
 
39
45
PGSQL_BASE = '/usr/share/postgresql'
40
46
 
41
 
A, B, C, D = 'ABCD' # tsearch2 ranking constants
 
47
# tsearch2 ranking constants:
 
48
A, B, C, D = 'ABCD'
42
49
 
43
50
# This data structure defines all of our full text indexes.  Each tuple in the
44
51
# top level list creates a 'fti' column in the specified table.
224
231
    # Create the trigger
225
232
    columns_and_weights = []
226
233
    for column, weight in qcolumns:
227
 
        columns_and_weights.extend( (column, weight) )
 
234
        columns_and_weights.extend((column, weight))
228
235
 
229
236
    sql = """
230
237
        CREATE TRIGGER tsvectorupdate BEFORE UPDATE OR INSERT ON %s
256
263
def liverebuild(con):
257
264
    """Rebuild the data in all the fti columns against possibly live database.
258
265
    """
259
 
    batch_size = 50 # Update maximum of this many rows per commit
 
266
    # Update number of rows per transaction.
 
267
    batch_size = 50
 
268
 
260
269
    cur = con.cursor()
261
270
    for table, ignored in ALL_FTI:
262
271
        table = quote_identifier(table)
316
325
        p = subprocess.Popen(
317
326
            cmd.split(' '), stdin=subprocess.PIPE,
318
327
            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
328
        tsearch2_sql = open(tsearch2_sql_path).read()
319
329
        out, err = p.communicate(
320
 
            "SET client_min_messages=ERROR; CREATE SCHEMA ts2;"
321
 
            + open(tsearch2_sql_path).read().replace('public;','ts2, public;'))
 
330
            "SET client_min_messages=ERROR; CREATE SCHEMA ts2;" +
 
331
            tsearch2_sql.replace('public;', 'ts2, public;'))
322
332
        if p.returncode != 0:
323
 
            log.fatal('Error executing %s:', cmd)
 
333
            log.fatal("Error executing %s:", cmd)
324
334
            log.debug(out)
325
 
            sys.exit(rv)
 
335
            sys.exit(p.returncode)
326
336
 
327
337
    # Create ftq helper and its sibling _ftq.
328
338
    # ftq(text) returns a tsquery, suitable for use querying the full text
363
373
        # Strip ! characters inside and at the end of a word
364
374
        query = re.sub(r"(?u)(?<=\w)[\!]+", " ", query)
365
375
 
366
 
        # Now that we have handle case sensitive booleans, convert to lowercase
 
376
        # Now that we have handled case-sensitive booleans, convert to
 
377
        # lowercase.
367
378
        query = query.lower()
368
379
 
369
380
        # Convert foo-bar to ((foo&bar)|foobar) and foo-bar-baz to
454
465
        p = plpy.prepare("SELECT to_tsquery('%s', $1) AS x", ["text"])
455
466
        query = plpy.execute(p, [query], 1)[0]["x"]
456
467
        return query or None
457
 
        """  % configuration
 
468
        """ % configuration
458
469
    sexecute(con, r"""
459
470
        CREATE OR REPLACE FUNCTION ts2._ftq(text) RETURNS text AS %s
460
471
        LANGUAGE plpythonu IMMUTABLE
569
580
    We know this by looking in our cache to see what the previous
570
581
    definitions were, and the --force command line argument
571
582
    '''
572
 
    current_columns = repr(sorted(columns)) # Convert to a string
 
583
    current_columns = repr(sorted(columns))
573
584
 
574
585
    existing = execute(
575
586
        con, "SELECT columns FROM FtiCache WHERE tablename=%(table)s",
621
632
# Files for output generated for slonik(1). None if not a Slony-I install.
622
633
slonik_sql = None
623
634
 
 
635
 
624
636
def main():
625
637
    parser = OptionParser()
626
638
    parser.add_option(
706
718
 
707
719
if __name__ == '__main__':
708
720
    sys.exit(main())
709
 
 
710