Revision 2715ade4 snf-pithos-backend/pithos/backends/lib/sqlalchemy/xfeatures.py
b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/xfeatures.py | ||
---|---|---|
1 | 1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
2 |
#
|
|
2 |
# |
|
3 | 3 |
# Redistribution and use in source and binary forms, with or |
4 | 4 |
# without modification, are permitted provided that the following |
5 | 5 |
# conditions are met: |
6 |
#
|
|
6 |
# |
|
7 | 7 |
# 1. Redistributions of source code must retain the above |
8 | 8 |
# copyright notice, this list of conditions and the following |
9 | 9 |
# disclaimer. |
10 |
#
|
|
10 |
# |
|
11 | 11 |
# 2. Redistributions in binary form must reproduce the above |
12 | 12 |
# copyright notice, this list of conditions and the following |
13 | 13 |
# disclaimer in the documentation and/or other materials |
14 | 14 |
# provided with the distribution. |
15 |
#
|
|
15 |
# |
|
16 | 16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
17 | 17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | 18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
... | ... | |
25 | 25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
26 | 26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
27 | 27 |
# POSSIBILITY OF SUCH DAMAGE. |
28 |
#
|
|
28 |
# |
|
29 | 29 |
# The views and conclusions contained in the software and |
30 | 30 |
# documentation are those of the authors and should not be |
31 | 31 |
# interpreted as representing official policies, either expressed |
... | ... | |
40 | 40 |
|
41 | 41 |
from dbworker import DBWorker |
42 | 42 |
|
43 |
|
|
43 | 44 |
def create_tables(engine): |
44 | 45 |
metadata = MetaData() |
45 |
columns=[]
|
|
46 |
columns = []
|
|
46 | 47 |
columns.append(Column('feature_id', Integer, primary_key=True)) |
47 | 48 |
columns.append(Column('path', String(2048))) |
48 | 49 |
xfeatures = Table('xfeatures', metadata, *columns, mysql_engine='InnoDB') |
49 | 50 |
# place an index on path |
50 | 51 |
Index('idx_features_path', xfeatures.c.path, unique=True) |
51 |
|
|
52 |
columns=[]
|
|
52 |
|
|
53 |
columns = []
|
|
53 | 54 |
columns.append(Column('feature_id', Integer, |
54 | 55 |
ForeignKey('xfeatures.feature_id', |
55 | 56 |
ondelete='CASCADE'), |
... | ... | |
57 | 58 |
columns.append(Column('key', Integer, primary_key=True, |
58 | 59 |
autoincrement=False)) |
59 | 60 |
columns.append(Column('value', String(256), primary_key=True)) |
60 |
xfeaturevals = Table('xfeaturevals', metadata, *columns, mysql_engine='InnoDB') |
|
61 |
|
|
61 |
xfeaturevals = Table( |
|
62 |
'xfeaturevals', metadata, *columns, mysql_engine='InnoDB') |
|
63 |
|
|
62 | 64 |
metadata.create_all(engine) |
63 | 65 |
return metadata.sorted_tables |
64 | 66 |
|
67 |
|
|
65 | 68 |
class XFeatures(DBWorker): |
66 | 69 |
"""XFeatures are path properties that allow non-nested |
67 | 70 |
inheritance patterns. Currently used for storing permissions. |
68 | 71 |
""" |
69 |
|
|
72 |
|
|
70 | 73 |
def __init__(self, **params): |
71 | 74 |
DBWorker.__init__(self, **params) |
72 | 75 |
try: |
... | ... | |
76 | 79 |
except NoSuchTableError: |
77 | 80 |
tables = create_tables(self.engine) |
78 | 81 |
map(lambda t: self.__setattr__(t.name, t), tables) |
79 |
|
|
82 |
|
|
80 | 83 |
# def xfeature_inherit(self, path): |
81 | 84 |
# """Return the (path, feature) inherited by the path, or None.""" |
82 |
#
|
|
85 |
# |
|
83 | 86 |
# s = select([self.xfeatures.c.path, self.xfeatures.c.feature_id]) |
84 | 87 |
# s = s.where(self.xfeatures.c.path <= path) |
85 | 88 |
# #s = s.where(self.xfeatures.c.path.like(self.escape_like(path) + '%', escape='\\')) # XXX: Implement reverse and escape like... |
... | ... | |
88 | 91 |
# l = r.fetchall() |
89 | 92 |
# r.close() |
90 | 93 |
# return l |
91 |
|
|
94 |
|
|
92 | 95 |
def xfeature_get(self, path): |
93 | 96 |
"""Return feature for path.""" |
94 |
|
|
97 |
|
|
95 | 98 |
s = select([self.xfeatures.c.feature_id]) |
96 | 99 |
s = s.where(self.xfeatures.c.path == path) |
97 | 100 |
s = s.order_by(self.xfeatures.c.path) |
... | ... | |
101 | 104 |
if row: |
102 | 105 |
return row[0] |
103 | 106 |
return None |
104 |
|
|
107 |
|
|
105 | 108 |
def xfeature_create(self, path): |
106 | 109 |
"""Create and return a feature for path. |
107 | 110 |
If the path has a feature, return it. |
108 | 111 |
""" |
109 |
|
|
112 |
|
|
110 | 113 |
feature = self.xfeature_get(path) |
111 | 114 |
if feature is not None: |
112 | 115 |
return feature |
... | ... | |
115 | 118 |
inserted_primary_key = r.inserted_primary_key[0] |
116 | 119 |
r.close() |
117 | 120 |
return inserted_primary_key |
118 |
|
|
121 |
|
|
119 | 122 |
def xfeature_destroy(self, path): |
120 | 123 |
"""Destroy a feature and all its key, value pairs.""" |
121 |
|
|
124 |
|
|
122 | 125 |
s = self.xfeatures.delete().where(self.xfeatures.c.path == path) |
123 | 126 |
r = self.conn.execute(s) |
124 | 127 |
r.close() |
125 |
|
|
128 |
|
|
126 | 129 |
def xfeature_destroy_bulk(self, paths): |
127 | 130 |
"""Destroy features and all their key, value pairs.""" |
128 |
|
|
131 |
|
|
129 | 132 |
s = self.xfeatures.delete().where(self.xfeatures.c.path.in_(paths)) |
130 | 133 |
r = self.conn.execute(s) |
131 | 134 |
r.close() |
132 |
|
|
135 |
|
|
133 | 136 |
def feature_dict(self, feature): |
134 | 137 |
"""Return a dict mapping keys to list of values for feature.""" |
135 |
|
|
138 |
|
|
136 | 139 |
s = select([self.xfeaturevals.c.key, self.xfeaturevals.c.value]) |
137 | 140 |
s = s.where(self.xfeaturevals.c.feature_id == feature) |
138 | 141 |
r = self.conn.execute(s) |
... | ... | |
141 | 144 |
d[key].append(value) |
142 | 145 |
r.close() |
143 | 146 |
return d |
144 |
|
|
147 |
|
|
145 | 148 |
def feature_set(self, feature, key, value): |
146 | 149 |
"""Associate a key, value pair with a feature.""" |
147 |
|
|
150 |
|
|
148 | 151 |
s = self.xfeaturevals.select() |
149 | 152 |
s = s.where(self.xfeaturevals.c.feature_id == feature) |
150 | 153 |
s = s.where(self.xfeaturevals.c.key == key) |
... | ... | |
156 | 159 |
s = self.xfeaturevals.insert() |
157 | 160 |
r = self.conn.execute(s, feature_id=feature, key=key, value=value) |
158 | 161 |
r.close() |
159 |
|
|
162 |
|
|
160 | 163 |
def feature_setmany(self, feature, key, values): |
161 | 164 |
"""Associate the given key, and values with a feature.""" |
162 |
|
|
165 |
|
|
163 | 166 |
#TODO: more efficient way to do it |
164 | 167 |
for v in values: |
165 | 168 |
self.feature_set(feature, key, v) |
166 |
|
|
169 |
|
|
167 | 170 |
def feature_unset(self, feature, key, value): |
168 | 171 |
"""Disassociate a key, value pair from a feature.""" |
169 |
|
|
172 |
|
|
170 | 173 |
s = self.xfeaturevals.delete() |
171 | 174 |
s = s.where(and_(self.xfeaturevals.c.feature_id == feature, |
172 |
self.xfeaturevals.c.key == key, |
|
173 |
self.xfeaturevals.c.value == value)) |
|
175 |
self.xfeaturevals.c.key == key,
|
|
176 |
self.xfeaturevals.c.value == value))
|
|
174 | 177 |
r = self.conn.execute(s) |
175 | 178 |
r.close() |
176 |
|
|
179 |
|
|
177 | 180 |
def feature_unsetmany(self, feature, key, values): |
178 | 181 |
"""Disassociate the key for the values given, from a feature.""" |
179 |
|
|
182 |
|
|
180 | 183 |
for v in values: |
181 | 184 |
conditional = and_(self.xfeaturevals.c.feature_id == feature, |
182 | 185 |
self.xfeaturevals.c.key == key, |
... | ... | |
184 | 187 |
s = self.xfeaturevals.delete().where(conditional) |
185 | 188 |
r = self.conn.execute(s) |
186 | 189 |
r.close() |
187 |
|
|
190 |
|
|
188 | 191 |
def feature_get(self, feature, key): |
189 | 192 |
"""Return the list of values for a key of a feature.""" |
190 |
|
|
193 |
|
|
191 | 194 |
s = select([self.xfeaturevals.c.value]) |
192 | 195 |
s = s.where(and_(self.xfeaturevals.c.feature_id == feature, |
193 |
self.xfeaturevals.c.key == key)) |
|
196 |
self.xfeaturevals.c.key == key))
|
|
194 | 197 |
r = self.conn.execute(s) |
195 | 198 |
l = [row[0] for row in r.fetchall()] |
196 | 199 |
r.close() |
197 | 200 |
return l |
198 |
|
|
201 |
|
|
199 | 202 |
def feature_clear(self, feature, key): |
200 | 203 |
"""Delete all key, value pairs for a key of a feature.""" |
201 |
|
|
204 |
|
|
202 | 205 |
s = self.xfeaturevals.delete() |
203 | 206 |
s = s.where(and_(self.xfeaturevals.c.feature_id == feature, |
204 |
self.xfeaturevals.c.key == key)) |
|
207 |
self.xfeaturevals.c.key == key))
|
|
205 | 208 |
r = self.conn.execute(s) |
206 | 209 |
r.close() |
Also available in: Unified diff