1 """provide an abstract class for external sources using a sqlite database helper |
1 """provide an abstract class for external sources using a sqlite database helper |
2 |
2 |
3 :organization: Logilab |
3 :organization: Logilab |
4 :copyright: 2007-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
4 :copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
6 """ |
6 """ |
7 __docformat__ = "restructuredtext en" |
7 __docformat__ = "restructuredtext en" |
8 |
8 |
9 |
9 |
10 import time |
10 import time |
11 import threading |
11 import threading |
12 from os.path import join, exists |
12 from os.path import join, exists |
13 |
13 |
14 from cubicweb import server |
14 from cubicweb import server |
15 from cubicweb.server.sqlutils import sqlexec, SQLAdapterMixIn |
15 from cubicweb.server.sqlutils import SQL_PREFIX, sqlexec, SQLAdapterMixIn |
16 from cubicweb.server.sources import AbstractSource, native |
16 from cubicweb.server.sources import AbstractSource, native |
17 from cubicweb.server.sources.rql2sql import SQLGenerator |
17 from cubicweb.server.sources.rql2sql import SQLGenerator |
18 |
18 |
19 def timeout_acquire(lock, timeout): |
19 def timeout_acquire(lock, timeout): |
20 while not lock.acquire(False): |
20 while not lock.acquire(False): |
120 cu = cnx.cursor() |
120 cu = cnx.cursor() |
121 schema = self.schema |
121 schema = self.schema |
122 for etype in self.support_entities: |
122 for etype in self.support_entities: |
123 eschema = schema.eschema(etype) |
123 eschema = schema.eschema(etype) |
124 createsqls = eschema2sql(self.sqladapter.dbhelper, eschema, |
124 createsqls = eschema2sql(self.sqladapter.dbhelper, eschema, |
125 skip_relations=('data',)) |
125 skip_relations=('data',), prefix=SQL_PREFIX) |
126 sqlexec(createsqls, cu, withpb=False) |
126 sqlexec(createsqls, cu, withpb=False) |
127 for rtype in self.support_relations: |
127 for rtype in self.support_relations: |
128 rschema = schema.rschema(rtype) |
128 rschema = schema.rschema(rtype) |
129 if not rschema.inlined: |
129 if not rschema.inlined: |
130 sqlexec(rschema2sql(rschema), cu, withpb=False) |
130 sqlexec(rschema2sql(rschema), cu, withpb=False) |
139 chown(self.dbpath, self.repo.config['uid']) |
139 chown(self.dbpath, self.repo.config['uid']) |
140 restrict_perms_to_user(self.dbpath, self.info) |
140 restrict_perms_to_user(self.dbpath, self.info) |
141 |
141 |
142 def set_schema(self, schema): |
142 def set_schema(self, schema): |
143 super(SQLiteAbstractSource, self).set_schema(schema) |
143 super(SQLiteAbstractSource, self).set_schema(schema) |
144 if self._need_sql_create and self._is_schema_complete(): |
144 if self._need_sql_create and self._is_schema_complete() and self.dbpath: |
145 self._create_database() |
145 self._create_database() |
146 self.rqlsqlgen = self.sqlgen_class(schema, self.sqladapter.dbhelper) |
146 self.rqlsqlgen = self.sqlgen_class(schema, self.sqladapter.dbhelper) |
147 |
147 |
148 def get_connection(self): |
148 def get_connection(self): |
149 return ConnectionWrapper(self) |
149 return ConnectionWrapper(self) |
194 don't want to simply do this, so let raise NotImplementedError and the |
194 don't want to simply do this, so let raise NotImplementedError and the |
195 source implementor may use this method if necessary |
195 source implementor may use this method if necessary |
196 """ |
196 """ |
197 cu = session.pool[self.uri] |
197 cu = session.pool[self.uri] |
198 attrs = self.sqladapter.preprocess_entity(entity) |
198 attrs = self.sqladapter.preprocess_entity(entity) |
199 sql = self.sqladapter.sqlgen.insert(str(entity.e_schema), attrs) |
199 sql = self.sqladapter.sqlgen.insert(SQL_PREFIX + str(entity.e_schema), attrs) |
200 cu.execute(sql, attrs) |
200 cu.execute(sql, attrs) |
201 |
201 |
202 def add_entity(self, session, entity): |
202 def add_entity(self, session, entity): |
203 """add a new entity to the source""" |
203 """add a new entity to the source""" |
204 raise NotImplementedError() |
204 raise NotImplementedError() |
211 and the source implementor may use this method if necessary |
211 and the source implementor may use this method if necessary |
212 """ |
212 """ |
213 cu = session.pool[self.uri] |
213 cu = session.pool[self.uri] |
214 if attrs is None: |
214 if attrs is None: |
215 attrs = self.sqladapter.preprocess_entity(entity) |
215 attrs = self.sqladapter.preprocess_entity(entity) |
216 sql = self.sqladapter.sqlgen.update(str(entity.e_schema), attrs, ['eid']) |
216 sql = self.sqladapter.sqlgen.update(SQL_PREFIX + str(entity.e_schema), attrs, ['eid']) |
217 cu.execute(sql, attrs) |
217 cu.execute(sql, attrs) |
218 |
218 |
219 def update_entity(self, session, entity): |
219 def update_entity(self, session, entity): |
220 """update an entity in the source""" |
220 """update an entity in the source""" |
221 raise NotImplementedError() |
221 raise NotImplementedError() |
226 this is not deleting a file in the svn but deleting entities from the |
226 this is not deleting a file in the svn but deleting entities from the |
227 source. Main usage is to delete repository content when a Repository |
227 source. Main usage is to delete repository content when a Repository |
228 entity is deleted. |
228 entity is deleted. |
229 """ |
229 """ |
230 sqlcursor = session.pool[self.uri] |
230 sqlcursor = session.pool[self.uri] |
231 attrs = {'eid': eid} |
231 attrs = {SQL_PREFIX + 'eid': eid} |
232 sql = self.sqladapter.sqlgen.delete(etype, attrs) |
232 sql = self.sqladapter.sqlgen.delete(SQL_PREFIX + etype, attrs) |
233 sqlcursor.execute(sql, attrs) |
233 sqlcursor.execute(sql, attrs) |
234 |
234 |
235 def delete_relation(self, session, subject, rtype, object): |
235 def delete_relation(self, session, subject, rtype, object): |
236 """delete a relation from the source""" |
236 """delete a relation from the source""" |
237 rschema = self.schema.rschema(rtype) |
237 rschema = self.schema.rschema(rtype) |
238 if rschema.inlined: |
238 if rschema.inlined: |
239 if subject in session.query_data('pendingeids', ()): |
239 if subject in session.query_data('pendingeids', ()): |
240 return |
240 return |
241 etype = session.describe(subject)[0] |
241 table = SQL_PREFIX + session.describe(subject)[0] |
242 sql = 'UPDATE %s SET %s=NULL WHERE eid=%%(eid)s' % (etype, rtype) |
242 column = SQL_PREFIX + rtype |
|
243 sql = 'UPDATE %s SET %s=NULL WHERE %seid=%%(eid)s' % (table, column, SQL_PREFIX) |
243 attrs = {'eid' : subject} |
244 attrs = {'eid' : subject} |
244 else: |
245 else: |
245 attrs = {'eid_from': subject, 'eid_to': object} |
246 attrs = {'eid_from': subject, 'eid_to': object} |
246 sql = self.sqladapter.sqlgen.delete('%s_relation' % rtype, attrs) |
247 sql = self.sqladapter.sqlgen.delete('%s_relation' % rtype, attrs) |
247 sqlcursor = session.pool[self.uri] |
248 sqlcursor = session.pool[self.uri] |