106 def set_entity_cache(self, entity): |
106 def set_entity_cache(self, entity): |
107 pass |
107 pass |
108 |
108 |
109 # XXX move to CWEntityManager or even better as factory method (unclear |
109 # XXX move to CWEntityManager or even better as factory method (unclear |
110 # where yet...) |
110 # where yet...) |
111 def create_entity(self, etype, *args, **kwargs): |
111 def create_entity(self, etype, **kwargs): |
112 """add a new entity of the given type |
112 """add a new entity of the given type |
113 |
113 |
114 Example (in a shell session): |
114 Example (in a shell session): |
115 |
115 |
116 c = create_entity('Company', name='Logilab') |
116 c = create_entity('Company', name=u'Logilab') |
117 create_entity('Person', ('works_for', 'Y'), Y=c.eid, firstname='John', lastname='Doe') |
117 create_entity('Person', works_for=c, firstname=u'John', lastname=u'Doe') |
|
118 |
118 """ |
119 """ |
119 rql = 'INSERT %s X' % etype |
120 rql = 'INSERT %s X' % etype |
120 relations = [] |
121 relations = [] |
121 restrictions = [] |
122 restrictions = set() |
122 cachekey = [] |
123 cachekey = [] |
123 for rtype, rvar in args: |
124 pending_relations = [] |
124 relations.append('X %s %s' % (rtype, rvar)) |
125 for attr, value in kwargs.iteritems(): |
125 restrictions.append('%s eid %%(%s)s' % (rvar, rvar)) |
126 if isinstance(value, (tuple, list, set, frozenset)): |
126 cachekey.append(rvar) |
127 if len(value) == 1: |
127 for attr in kwargs: |
128 value = iter(value).next() |
128 if attr in cachekey: |
129 else: |
129 continue |
130 pending_relations.append( (attr, value) ) |
130 relations.append('X %s %%(%s)s' % (attr, attr)) |
131 continue |
|
132 if hasattr(value, 'eid'): # non final relation |
|
133 rvar = attr.upper() |
|
134 # XXX safer detection of object relation |
|
135 if attr.startswith('reverse_'): |
|
136 relations.append('%s %s X' % (rvar, attr[len('reverse_'):])) |
|
137 else: |
|
138 relations.append('X %s %s' % (attr, rvar)) |
|
139 restriction = '%s eid %%(%s)s' % (rvar, attr) |
|
140 if not restriction in restrictions: |
|
141 restrictions.add(restriction) |
|
142 cachekey.append(attr) |
|
143 kwargs[attr] = value.eid |
|
144 else: # attribute |
|
145 relations.append('X %s %%(%s)s' % (attr, attr)) |
131 if relations: |
146 if relations: |
132 rql = '%s: %s' % (rql, ', '.join(relations)) |
147 rql = '%s: %s' % (rql, ', '.join(relations)) |
133 if restrictions: |
148 if restrictions: |
134 rql = '%s WHERE %s' % (rql, ', '.join(restrictions)) |
149 rql = '%s WHERE %s' % (rql, ', '.join(restrictions)) |
135 return self.execute(rql, kwargs, cachekey).get_entity(0, 0) |
150 created = self.execute(rql, kwargs, cachekey).get_entity(0, 0) |
|
151 for attr, values in pending_relations: |
|
152 if attr.startswith('reverse_'): |
|
153 restr = 'Y %s X' % attr[len('reverse_'):] |
|
154 else: |
|
155 restr = 'X %s Y' % attr |
|
156 self.execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % ( |
|
157 restr, ','.join(str(r.eid) for r in values)), |
|
158 {'x': created.eid}, 'x') |
|
159 return created |
136 |
160 |
137 def ensure_ro_rql(self, rql): |
161 def ensure_ro_rql(self, rql): |
138 """raise an exception if the given rql is not a select query""" |
162 """raise an exception if the given rql is not a select query""" |
139 first = rql.split(' ', 1)[0].lower() |
163 first = rql.split(' ', 1)[0].lower() |
140 if first in ('insert', 'set', 'delete'): |
164 if first in ('insert', 'set', 'delete'): |