Merge lp:~ricardokirkner/django-pgtools/check-exists-before-grant into lp:django-pgtools

Proposed by Ricardo Kirkner
Status: Merged
Approved by: Matias Bordese
Approved revision: 8
Merged at revision: 7
Proposed branch: lp:~ricardokirkner/django-pgtools/check-exists-before-grant
Merge into: lp:django-pgtools
Diff against target: 87 lines (+40/-5)
2 files modified
pgtools/management/commands/grantuser.py (+14/-4)
pgtools/tests.py (+26/-1)
To merge this branch: bzr merge lp:~ricardokirkner/django-pgtools/check-exists-before-grant
Reviewer Review Type Date Requested Status
Matias Bordese (community) Approve
Review via email: mp+149932@code.launchpad.net

Commit message

Before requesting a GRANT operation, make sure the relation actually exists, to avoid causing errors on the cursor.

Description of the change

Before requesting a GRANT operation, make sure the relation actually exists, to avoid causing errors on the cursor.

This aims specifically at fixing the issue as seen on https://pastebin.canonical.com/85297/

To post a comment you must log in.
8. By Ricardo Kirkner

fixed review comments

- styling issue
- added test to verify result without mocking cursor.fetchone

Revision history for this message
Matias Bordese (matiasb) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'pgtools/management/commands/grantuser.py'
2--- pgtools/management/commands/grantuser.py 2012-04-13 17:32:45 +0000
3+++ pgtools/management/commands/grantuser.py 2013-02-21 21:19:22 +0000
4@@ -11,6 +11,7 @@
5
6
7 GRANT_SQL = "GRANT ALL ON %s TO %s;"
8+EXISTS_SQL = "SELECT 1 FROM pg_class WHERE relname='%s';"
9
10
11 class Command(BaseCommand):
12@@ -34,10 +35,13 @@
13 for model in get_models():
14 # grant access to model
15 table = model._meta.db_table
16- self._grant_one(table)
17- if model._meta.has_auto_field:
18- sequence = "%s_%s_seq" % (table, model._meta.auto_field.column)
19- self._grant_one(sequence)
20+ if self._check_exists(table):
21+ self._grant_one(table)
22+ if model._meta.has_auto_field:
23+ sequence = "%s_%s_seq" % (table,
24+ model._meta.auto_field.column)
25+ if self._check_exists(sequence):
26+ self._grant_one(sequence)
27
28 # grant access to model relations
29 for f in model._meta.many_to_many:
30@@ -46,6 +50,12 @@
31 if not getattr(connection.features, 'uses_autocommit', False):
32 connection.connection.commit()
33
34+ def _check_exists(self, table_or_sequence):
35+ sql = EXISTS_SQL % table_or_sequence
36+ self.cursor.execute(sql)
37+ result = self.cursor.fetchone()
38+ return bool(result)
39+
40 def _grant_one(self, table_or_sequence):
41 print 'Granting access to', table_or_sequence
42 sql = GRANT_SQL % (table_or_sequence, self.username)
43
44=== modified file 'pgtools/tests.py'
45--- pgtools/tests.py 2013-02-21 15:01:28 +0000
46+++ pgtools/tests.py 2013-02-21 21:19:22 +0000
47@@ -17,7 +17,7 @@
48 from django.conf import settings
49 from django.core.management import call_command
50 from django.core.management.base import CommandError
51-from django.db import connection
52+from django.db import connection, models
53 from django.db.backends import postgresql_psycopg2
54 from django.db.models.loading import get_models
55 from django.db.utils import load_backend
56@@ -570,6 +570,31 @@
57 (('django_admin_log_id_seq',), {}))
58
59 @patch('pgtools.management.commands.grantuser.get_models')
60+ def test_command_grantuser_missing_relations(self, mock_get_models):
61+ # create table without sequence
62+ sql = "CREATE TABLE pgtools_foo (id integer PRIMARY KEY);"
63+ cursor = connection.cursor()
64+ cursor.execute(sql)
65+
66+ class Foo(models.Model):
67+ foo = models.IntegerField()
68+
69+ mock_get_models.return_value = [Foo]
70+ command = grantuser.Command
71+ with patch.object(command, '_grant_one') as mock_grant_one:
72+ # force the cache to reload the apps
73+ try:
74+ call_command('grantuser', 'payments')
75+ except:
76+ self.fail('Error while calling grantuser command')
77+
78+ # assert the grant table method was called on all model tables
79+ self.assertEqual(mock_grant_one.call_args_list[0],
80+ (('pgtools_foo',), {}))
81+ # assert nothing else was processed
82+ self.assertEqual(len(mock_grant_one.call_args_list), 1)
83+
84+ @patch('pgtools.management.commands.grantuser.get_models')
85 @patch('pgtools.management.commands.grantuser.connection')
86 def test__grant_many_to_many(self, mock_connection, mock_get_models):
87 mock_connection.cursor.return_value.fetchone.return_value = ['foo']

Subscribers

People subscribed via source and target branches