← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~stevenk/launchpad/db-merge-stable-redux into lp:launchpad

 

Steve Kowalik has proposed merging lp:~stevenk/launchpad/db-merge-stable-redux into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~stevenk/launchpad/db-merge-stable-redux/+merge/87298

Merge stable at r14617.
-- 
https://code.launchpad.net/~stevenk/launchpad/db-merge-stable-redux/+merge/87298
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/db-merge-stable-redux into lp:launchpad.
=== modified file 'database/sampledata/current-dev.sql'
--- database/sampledata/current-dev.sql	2011-12-13 15:21:25 +0000
+++ database/sampledata/current-dev.sql	2012-01-02 22:37:27 +0000
@@ -1,6 +1,6 @@
 -- Copyright 2010-2011 Canonical Ltd.  This software is licensed under the
 -- GNU Affero General Public License version 3 (see the file LICENSE).
--- Created using pg_dump (PostgreSQL) 8.4.8
+-- Created using pg_dump (PostgreSQL) 8.4.9
 
 SET check_function_bodies = false;
 SET client_encoding = 'UTF8';
@@ -5752,6 +5752,13 @@
 ALTER TABLE messagechunk ENABLE TRIGGER ALL;
 
 
+ALTER TABLE milestonetag DISABLE TRIGGER ALL;
+
+
+
+ALTER TABLE milestonetag ENABLE TRIGGER ALL;
+
+
 ALTER TABLE mirror DISABLE TRIGGER ALL;
 
 

=== modified file 'database/sampledata/current.sql'
--- database/sampledata/current.sql	2011-12-13 15:21:25 +0000
+++ database/sampledata/current.sql	2012-01-02 22:37:27 +0000
@@ -1,6 +1,6 @@
 -- Copyright 2010-2011 Canonical Ltd.  This software is licensed under the
 -- GNU Affero General Public License version 3 (see the file LICENSE).
--- Created using pg_dump (PostgreSQL) 8.4.8
+-- Created using pg_dump (PostgreSQL) 8.4.9
 
 SET check_function_bodies = false;
 SET client_encoding = 'UTF8';
@@ -5682,6 +5682,13 @@
 ALTER TABLE messagechunk ENABLE TRIGGER ALL;
 
 
+ALTER TABLE milestonetag DISABLE TRIGGER ALL;
+
+
+
+ALTER TABLE milestonetag ENABLE TRIGGER ALL;
+
+
 ALTER TABLE mirror DISABLE TRIGGER ALL;
 
 

=== modified file 'database/schema/comments.sql'
--- database/schema/comments.sql	2011-11-17 13:06:30 +0000
+++ database/schema/comments.sql	2012-01-02 22:37:27 +0000
@@ -2425,3 +2425,8 @@
 'OpenId Identifiers that can be used to log into an Account.';
 COMMENT ON COLUMN OpenIdIdentifier.identifier IS
 'OpenId Identifier. This should be a URL, but is currently just a token that can be used to generate the Identity URL for the Canonical SSO OpenId Provider.';
+
+-- MilestoneTag
+COMMENT ON TABLE milestonetag IS 'Attaches simple text tags to a milestone.';
+COMMENT ON COLUMN milestonetag.milestone IS 'The milestone the tag is attached to.';
+COMMENT ON COLUMN milestonetag.tag IS 'The text representation of the tag.';

=== modified file 'database/schema/fti.py'
--- database/schema/fti.py	2011-12-31 00:07:44 +0000
+++ database/schema/fti.py	2012-01-02 22:37:27 +0000
@@ -11,6 +11,8 @@
 """
 __metaclass__ = type
 
+import _pythonpath
+
 from distutils.version import LooseVersion
 from optparse import OptionParser
 import os.path
@@ -20,24 +22,23 @@
 from textwrap import dedent
 import time
 
-import _pythonpath
 import psycopg2.extensions
-import replication.helpers
 
-from canonical.config import config
-from canonical.database.postgresql import ConnectionString
-from canonical.database.sqlbase import (
+from lp.services.config import config
+from lp.services.database.postgresql import ConnectionString
+from lp.services.database.sqlbase import (
     connect,
     ISOLATION_LEVEL_AUTOCOMMIT,
     ISOLATION_LEVEL_READ_COMMITTED,
     quote,
     quote_identifier,
     )
-from canonical.launchpad.scripts import (
+from lp.services.scripts import (
     db_options,
     logger,
     logger_options,
     )
+import replication.helpers
 
 # Defines parser and locale to use.
 DEFAULT_CONFIG = 'default'

=== added file 'database/schema/patch-2209-00-3.sql'
--- database/schema/patch-2209-00-3.sql	1970-01-01 00:00:00 +0000
+++ database/schema/patch-2209-00-3.sql	2012-01-02 22:37:27 +0000
@@ -0,0 +1,22 @@
+-- Copyright 2011 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+CREATE TABLE milestonetag (
+    id SERIAL PRIMARY KEY,
+    milestone integer NOT NULL REFERENCES milestone ON DELETE CASCADE,
+    tag text NOT NULL,
+    date_created timestamp without time zone DEFAULT
+        timezone('UTC'::text, now()) NOT NULL,
+    created_by integer NOT NULL REFERENCES person,
+    CONSTRAINT valid_tag CHECK (valid_name(tag))
+);
+
+ALTER TABLE ONLY milestonetag
+    ADD CONSTRAINT milestonetag__tag__milestone__key UNIQUE (tag, milestone);
+
+CREATE INDEX milestonetag__milestones_idx
+    ON milestonetag USING btree (milestone);
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2209, 0, 3);

=== added file 'database/schema/patch-2209-00-4.sql'
--- database/schema/patch-2209-00-4.sql	1970-01-01 00:00:00 +0000
+++ database/schema/patch-2209-00-4.sql	2012-01-02 22:37:27 +0000
@@ -0,0 +1,57 @@
+SET client_min_messages=ERROR;
+
+CREATE OR REPLACE FUNCTION check_email_address_person_account(
+    person integer, account integer)
+    RETURNS boolean
+    LANGUAGE plpythonu IMMUTABLE RETURNS NULL ON NULL INPUT AS
+$$
+    # It's possible for an EmailAddress to be created without an
+    # account. If that happens, and this function is called, we return
+    # True so as to avoid breakages.
+    if account is None:
+        return True
+    results = plpy.execute("""
+        SELECT account FROM Person WHERE id = %s""" % person)
+    # If there are no accounts with that Person in the DB, or the Person
+    # is new and hasn't yet been linked to an account, return success
+    # anyway. This helps avoid the PGRestore breaking (and referential
+    # integrity will prevent this from causing bugs later.
+    if results.nrows() == 0 or results[0]['account'] is None:
+        return True
+    return results[0]['account'] == account
+$$;
+
+COMMENT ON FUNCTION check_email_address_person_account(integer, integer) IS
+'Check that the person to which an email address is linked has the same account as that email address.';
+
+CREATE OR REPLACE FUNCTION check_person_email_address_account(
+    person integer, account integer)
+    RETURNS boolean
+    LANGUAGE plpythonu IMMUTABLE RETURNS NULL ON NULL INPUT AS
+$$
+    # It's possible for a Person to be created without an account. If
+    # that happens, return True so that things don't break.
+    if account is None:
+        return True
+    email_address_accounts = plpy.execute("""
+        SELECT account FROM EmailAddress WHERE
+            person = %s AND account IS NOT NULL""" % person)
+    # If there are no email address accounts to check, we're done.
+    if email_address_accounts.nrows() == 0:
+        return True
+    for email_account_row in email_address_accounts:
+        email_account = email_account_row['account']
+        if email_account is not None and email_account != account:
+            return False
+    return True
+$$;
+
+COMMENT ON FUNCTION check_person_email_address_account(integer, integer) IS
+'Check that the email addresses linked to a person have the same account ID as that person.';
+
+ALTER TABLE EmailAddress ADD CONSTRAINT valid_account_for_person
+    CHECK (check_email_address_person_account(person, account));
+ALTER TABLE Person ADD CONSTRAINT valid_account_for_emailaddresses
+    CHECK (check_person_email_address_account(id, account));
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2209, 00, 4);

=== modified file 'database/schema/security.cfg'
--- database/schema/security.cfg	2011-12-23 11:57:21 +0000
+++ database/schema/security.cfg	2012-01-02 22:37:27 +0000
@@ -18,6 +18,8 @@
 public.bug_update_latest_patch_uploaded(integer) =
 public.bugnotificationarchive              =
 public.calculate_bug_heat(integer)         = EXECUTE
+public.check_email_address_person_account(integer, integer) = EXECUTE
+public.check_person_email_address_account(integer, integer) = EXECUTE
 public.cursor_fetch(refcursor, integer)    = EXECUTE
 public.databasediskutilization             =
 public.debversion(character)                           = EXECUTE
@@ -221,6 +223,7 @@
 public.messageapproval                  = SELECT, INSERT, UPDATE, DELETE
 public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT, INSERT, UPDATE, DELETE
+public.milestonetag                     = SELECT, INSERT, UPDATE, DELETE
 public.mirrorcdimagedistroseries        = SELECT, INSERT, DELETE
 public.mirrordistroarchseries           = SELECT, INSERT, DELETE, UPDATE
 public.mirrordistroseriessource         = SELECT, INSERT, UPDATE, DELETE
@@ -591,6 +594,7 @@
 public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
+public.milestonetag                     = SELECT
 public.person                           = SELECT, INSERT, UPDATE
 public.personlanguage                   = SELECT
 public.personsettings                   = SELECT, INSERT
@@ -649,6 +653,7 @@
 public.karmaaction                        = SELECT
 public.message                            = SELECT, INSERT
 public.messagechunk                       = SELECT, INSERT
+public.milestonetag                       = SELECT
 public.person                             = SELECT
 public.revision                           = SELECT, INSERT, UPDATE
 public.revisionauthor                     = SELECT, INSERT, UPDATE
@@ -862,6 +867,7 @@
 public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
+public.milestonetag                     = SELECT
 public.packagecopyjob                   = SELECT, INSERT, DELETE
 public.packagecopyrequest               = SELECT, INSERT, UPDATE
 public.packagediff                      = SELECT, INSERT, UPDATE
@@ -1301,6 +1307,7 @@
 public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
+public.milestonetag                     = SELECT
 public.packagebuild                     = SELECT, INSERT, UPDATE
 public.packagecopyjob                   = SELECT, INSERT
 public.packagediff                      = SELECT, INSERT, UPDATE, DELETE
@@ -1404,6 +1411,7 @@
 public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
+public.milestonetag                     = SELECT
 public.packagebuild                     = SELECT, INSERT, UPDATE
 public.packagecopyjob                   = SELECT, INSERT, UPDATE
 public.packagediff                      = SELECT, UPDATE
@@ -1502,6 +1510,7 @@
 public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
+public.milestonetag                     = SELECT
 public.person                           = SELECT
 public.personlanguage                   = SELECT
 public.personsettings                   = SELECT
@@ -1706,6 +1715,7 @@
 public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
 public.milestone                        = SELECT
+public.milestonetag                     = SELECT, INSERT, DELETE
 public.packageset                       = SELECT
 public.packagesetgroup                  = SELECT
 public.packagesetinclusion              = SELECT
@@ -1946,6 +1956,7 @@
 public.job                              = SELECT, INSERT, UPDATE
 public.message                          = SELECT, INSERT
 public.messagechunk                     = SELECT, INSERT
+public.milestonetag                     = SELECT
 public.person                           = SELECT, INSERT
 public.personsettings                   = SELECT, INSERT
 public.product                          = SELECT, INSERT, UPDATE
@@ -2044,6 +2055,7 @@
 public.message                          = SELECT, UPDATE
 public.messageapproval                  = SELECT, UPDATE
 public.milestone                        = SELECT, UPDATE
+public.milestonetag                     = SELECT, INSERT, UPDATE, DELETE
 public.mirror                           = SELECT, UPDATE
 public.nameblacklist                    = SELECT, UPDATE
 public.oauthaccesstoken                 = SELECT, UPDATE
@@ -2146,6 +2158,7 @@
 public.job                              = SELECT, INSERT, DELETE
 public.logintoken                       = SELECT, DELETE
 public.mailinglistsubscription          = SELECT, DELETE
+public.milestonetag                     = SELECT
 public.oauthnonce                       = SELECT, DELETE
 public.openidconsumerassociation        = SELECT, DELETE
 public.openidconsumernonce              = SELECT, DELETE

=== removed symlink 'lib/canonical/config/__init__.py'
=== target was u'../../lp/services/config/__init__.py'
=== removed directory 'lib/canonical/database'
=== removed file 'lib/canonical/database/__init__.py'
=== removed file 'lib/canonical/database/postgresql.py'
--- lib/canonical/database/postgresql.py	2011-12-31 00:07:44 +0000
+++ lib/canonical/database/postgresql.py	1970-01-01 00:00:00 +0000
@@ -1,10 +0,0 @@
-# Copyright 2011 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-# Temporary shim for fti.py.
-
-__all__ = [
-    'ConnectionString',
-    ]
-
-from lp.services.database.postgresql import ConnectionString

=== removed file 'lib/canonical/database/sqlbase.py'
--- lib/canonical/database/sqlbase.py	2011-12-31 00:07:44 +0000
+++ lib/canonical/database/sqlbase.py	1970-01-01 00:00:00 +0000
@@ -1,20 +0,0 @@
-# Copyright 2011 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-# Temporary shim for fti.py.
-
-__all__ = [
-    'connect',
-    'ISOLATION_LEVEL_AUTOCOMMIT',
-    'ISOLATION_LEVEL_READ_COMMITTED',
-    'quote',
-    'quote_identifier',
-    ]
-
-from lp.services.database.sqlbase import (
-    connect,
-    ISOLATION_LEVEL_AUTOCOMMIT,
-    ISOLATION_LEVEL_READ_COMMITTED,
-    quote,
-    quote_identifier,
-    )

=== removed directory 'lib/canonical/launchpad/scripts'
=== removed file 'lib/canonical/launchpad/scripts/__init__.py'
--- lib/canonical/launchpad/scripts/__init__.py	2011-12-22 04:36:01 +0000
+++ lib/canonical/launchpad/scripts/__init__.py	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-# This is a temporary shim to support database/schema/fti.py in devel.
-
-__all__ = [
-    'db_options',
-    'logger',
-    'logger_options',
-    ]
-
-from lp.services.scripts import (
-    db_options,
-    logger,
-    logger_options,
-    )

=== modified file 'lib/lp/registry/tests/test_person.py'
--- lib/lp/registry/tests/test_person.py	2011-12-30 06:14:56 +0000
+++ lib/lp/registry/tests/test_person.py	2012-01-02 22:37:27 +0000
@@ -55,7 +55,10 @@
     IMasterStore,
     IStore,
     )
-from lp.services.database.sqlbase import cursor
+from lp.services.database.sqlbase import (
+    cursor,
+    sqlvalues,
+    )
 from lp.services.identity.interfaces.account import (
     AccountCreationRationale,
     AccountStatus,
@@ -847,8 +850,17 @@
         with celebrity_logged_in('admin'):
             email = from_person.preferredemail
             email.status = EmailAddressStatus.NEW
-            email.person = to_person
-            email.account = to_person.account
+            store = IMasterStore(EmailAddress)
+            # EmailAddress.acount and .person need to be updated at the
+            # same time to prevent the constraints on the account field
+            # from kicking the change out.
+            store.execute("""
+                UPDATE EmailAddress SET
+                    person = %s,
+                    account = %s
+                WHERE id = %s
+                """ % sqlvalues(
+                to_person.id, to_person.accountID, email.id))
         transaction.commit()
 
     def _do_merge(self, from_person, to_person, reviewer=None):