Skip to content

Commit efdca67

Browse files
committed
Schema for subscriptions
Create table for subscriptions. Populate table with subscriptions for attachments and revisions. Subscriptions will support multiple repositories and Git, even though code comments themselves don't currently (#13 and #14).
1 parent 0fa54f4 commit efdca67

2 files changed

Lines changed: 85 additions & 22 deletions

File tree

code_comments/db.py

Lines changed: 84 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
from trac.core import *
1+
from trac.core import Component, implements
22
from trac.db.schema import Table, Column, Index
33
from trac.env import IEnvironmentSetupParticipant
44
from trac.db.api import DatabaseManager
55

66
# Database version identifier for upgrades.
7-
db_version = 2
7+
db_version = 3
88

99
# Database schema
1010
schema = {
@@ -21,61 +21,119 @@
2121
Index(['path']),
2222
Index(['author']),
2323
],
24+
'code_comments_subscriptions': Table('code_comments_subscriptions',
25+
key=('user', 'type', 'path',
26+
'repos', 'rev'))[
27+
Column('user'),
28+
Column('usertype'),
29+
Column('type'),
30+
Column('path'),
31+
Column('repos'),
32+
Column('rev'),
33+
Index(['user']),
34+
Index(['path']),
35+
],
2436
}
2537

38+
2639
def to_sql(env, table):
2740
""" Convenience function to get the to_sql for the active connector."""
2841
dc = DatabaseManager(env)._get_connector()[0]
2942
return dc.to_sql(table)
3043

44+
3145
def create_tables(env, db):
3246
cursor = db.cursor()
3347
for table_name in schema:
3448
for stmt in to_sql(env, schema[table_name]):
3549
cursor.execute(stmt)
36-
cursor.execute("INSERT into system values ('code_comments_schema_version', %s)",
37-
str(db_version))
50+
cursor.execute(
51+
"insert into system values ('code_comments_schema_version', %s)",
52+
str(db_version))
53+
3854

3955
# Upgrades
56+
4057
def upgrade_from_1_to_2(env, db):
4158
# Add the new column "type"
4259
@env.with_transaction()
43-
def add_type_column( db ):
60+
def add_type_column(db):
4461
cursor = db.cursor()
45-
cursor.execute( 'ALTER TABLE code_comments ADD COLUMN type TEXT' )
62+
cursor.execute('ALTER TABLE code_comments ADD COLUMN type TEXT')
4663

4764
# Convert all the current comments to the new schema
4865
@env.with_transaction()
49-
def convert_comments( db ):
66+
def convert_comments(db):
5067
comments = {}
5168
cursor = db.cursor()
52-
cursor.execute( 'SELECT id, path FROM code_comments' )
69+
cursor.execute('SELECT id, path FROM code_comments')
5370
comments = cursor.fetchall()
5471
# options:
5572
# 1: comment on file (path != "" && path != "attachment")
5673
# 2: comment on changeset (path == "")
5774
# 3: comment on attachment (path == "attachment")
5875
for comment in comments:
5976
path = comment[1]
60-
is_comment_to_attachment = path.startswith( 'attachment' )
77+
is_comment_to_attachment = path.startswith('attachment')
6178
is_comment_to_file = not is_comment_to_attachment and '' != path
6279
is_comment_to_changeset = '' == path
6380
cursor = db.cursor()
6481
update = 'UPDATE code_comments SET type={0} WHERE id={1}'
6582
sql = ''
6683

6784
if is_comment_to_changeset:
68-
sql = update.format( "'changeset'", str( comment[0] ) )
85+
sql = update.format("'changeset'", str(comment[0]))
6986
elif is_comment_to_attachment:
70-
sql = update.format( "'attachment'", str(comment[0] ) )
87+
sql = update.format("'attachment'", str(comment[0]))
7188
elif is_comment_to_file:
72-
sql = update.format( "'browser'", str(comment[0] ) )
89+
sql = update.format("'browser'", str(comment[0]))
90+
91+
cursor.execute(sql)
92+
93+
94+
def upgrade_from_2_to_3(env, db):
95+
# Add the new table
96+
@env.with_transaction()
97+
def add_subscriptions_table(db):
98+
cursor = db.cursor()
99+
for stmt in to_sql(env, schema['code_comments_subscriptions']):
100+
cursor.execute(stmt)
101+
102+
@env.with_transaction()
103+
def add_attachment_subscriptions(db):
104+
"""
105+
Create a subscription for all existing attachments.
106+
"""
107+
cursor = db.cursor()
108+
cursor.execute("SELECT type, id, filename, author FROM attachment")
109+
attachments = cursor.fetchall()
110+
for attachment in attachments:
111+
path = "/{0}/{1}/{2}".format(*attachment)
112+
sql = ("INSERT INTO code_comments_subscriptions VALUES "
113+
"('{3}', 'author', 'attachment', '{path}', '', '')"
114+
).format(*attachment, path=path)
115+
cursor.execute(sql)
116+
117+
@env.with_transaction()
118+
def add_revision_subscriptions(db):
119+
"""
120+
Create a subscription for all existing revisions.
121+
"""
122+
cursor = db.cursor()
123+
cursor.execute("SELECT repos, rev, author FROM revision")
124+
revisions = cursor.fetchall()
125+
for revision in revisions:
126+
sql = ("INSERT INTO code_comments_subscriptions VALUES "
127+
"('{2}', 'author', 'revision', '', '{0}', '{1}')"
128+
).format(*revision)
129+
cursor.execute(sql)
73130

74-
cursor.execute( sql )
75131

76132
upgrade_map = {
77-
2: upgrade_from_1_to_2
78-
}
133+
2: upgrade_from_1_to_2,
134+
3: upgrade_from_2_to_3,
135+
}
136+
79137

80138
class CodeCommentsSetup(Component):
81139
"""Component that deals with database setup and upgrades."""
@@ -87,13 +145,17 @@ def environment_created(self):
87145
pass
88146

89147
def environment_needs_upgrade(self, db):
90-
"""Called when Trac checks whether the environment needs to be upgraded.
91-
Returns `True` if upgrade is needed, `False` otherwise."""
148+
"""
149+
Called when Trac checks whether the environment needs to be upgraded.
150+
Returns `True` if upgrade is needed, `False` otherwise.
151+
"""
92152
return self._get_version(db) != db_version
93153

94154
def upgrade_environment(self, db):
95-
"""Actually perform an environment upgrade, but don't commit as
96-
that is done by the common upgrade procedure when all plugins are done."""
155+
"""
156+
Actually perform an environment upgrade, but don't commit as
157+
that is done by the common upgrade procedure when all plugins are done.
158+
"""
97159
current_ver = self._get_version(db)
98160
if current_ver == 0:
99161
create_tables(self.env, db)
@@ -102,8 +164,9 @@ def upgrade_environment(self, db):
102164
upgrade_map[current_ver+1](self.env, db)
103165
current_ver += 1
104166
cursor = db.cursor()
105-
cursor.execute("UPDATE system SET value=%s WHERE name='code_comments_schema_version'",
106-
str(db_version))
167+
cursor.execute(
168+
"UPDATE system SET value=%s WHERE name='code_comments_schema_version'",
169+
str(db_version))
107170

108171
def _get_version(self, db):
109172
cursor = db.cursor()

todo.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Need to figure out how to handle blanket subscriptions.
2323
## Subscriptions
2424

2525
- [ ] model
26-
- [ ] db
26+
- [x] db
2727
- [ ] api - create, update, delete, query
2828

2929
## Listeners

0 commit comments

Comments
 (0)