219 if not quiet: |
223 if not quiet: |
220 pb_size = len(aller) + len(CONSTRAINTS) + len([x for x in eschemas if x.specializes()]) |
224 pb_size = len(aller) + len(CONSTRAINTS) + len([x for x in eschemas if x.specializes()]) |
221 pb = ProgressBar(pb_size, title=_title) |
225 pb = ProgressBar(pb_size, title=_title) |
222 else: |
226 else: |
223 pb = None |
227 pb = None |
|
228 groupmap = group_mapping(cursor, interactive=False) |
224 # serialize all entity types, assuring CWEType is serialized first |
229 # serialize all entity types, assuring CWEType is serialized first |
225 eschemas.remove(schema.eschema('CWEType')) |
230 eschemas.remove(schema.eschema('CWEType')) |
226 eschemas.insert(0, schema.eschema('CWEType')) |
231 eschemas.insert(0, schema.eschema('CWEType')) |
227 for eschema in eschemas: |
232 for eschema in eschemas: |
228 execschemarql(execute, eschema, eschema2rql(eschema, groupmap)) |
233 execschemarql(execute, eschema, eschema2rql(eschema, groupmap)) |
229 if pb is not None: |
234 if pb is not None: |
230 pb.update() |
235 pb.update() |
231 # serialize constraint types |
236 # serialize constraint types |
|
237 cstrtypemap = {} |
232 rql = 'INSERT CWConstraintType X: X name %(ct)s' |
238 rql = 'INSERT CWConstraintType X: X name %(ct)s' |
233 for cstrtype in CONSTRAINTS: |
239 for cstrtype in CONSTRAINTS: |
234 execute(rql, {'ct': unicode(cstrtype)}, build_descr=False) |
240 cstrtypemap[cstrtype] = execute(rql, {'ct': unicode(cstrtype)}, |
|
241 build_descr=False)[0][0] |
235 if pb is not None: |
242 if pb is not None: |
236 pb.update() |
243 pb.update() |
237 # serialize relations |
244 # serialize relations |
238 for rschema in schema.relations(): |
245 for rschema in schema.relations(): |
239 # skip virtual relations such as eid, has_text and identity |
246 # skip virtual relations such as eid, has_text and identity |
240 if rschema in VIRTUAL_RTYPES: |
247 if rschema in VIRTUAL_RTYPES: |
241 if pb is not None: |
248 if pb is not None: |
242 pb.update() |
249 pb.update() |
243 continue |
250 continue |
244 for rql, kwargs in erschema2rql(schema[ertype], groupmap): |
251 execschemarql(execute, rschema, rschema2rql(rschema, addrdef=False)) |
245 execute(rql, kwargs, build_descr=False) |
252 if rschema.symmetric: |
|
253 rdefs = [rdef for k, rdef in rschema.rdefs.iteritems() |
|
254 if (rdef.subject, rdef.object) == k] |
|
255 else: |
|
256 rdefs = rschema.rdefs.itervalues() |
|
257 for rdef in rdefs: |
|
258 execschemarql(execute, rdef, |
|
259 rdef2rql(rdef, cstrtypemap, groupmap)) |
246 if pb is not None: |
260 if pb is not None: |
247 pb.update() |
261 pb.update() |
248 for rql, kwargs in specialize2rql(schema): |
262 for rql, kwargs in specialize2rql(schema): |
249 assert execute(rql, kwargs, build_descr=False) |
263 assert execute(rql, kwargs, build_descr=False) |
250 if pb is not None: |
264 if pb is not None: |
251 pb.update() |
265 pb.update() |
252 if not quiet: |
266 if not quiet: |
253 print |
267 print |
254 |
268 |
|
269 |
|
270 # high level serialization functions |
|
271 |
|
272 def execschemarql(execute, schema, rqls): |
|
273 for rql, kwargs in rqls: |
|
274 kwargs['x'] = schema.eid |
|
275 rset = execute(rql, kwargs, build_descr=False) |
|
276 if schema.eid is None: |
|
277 schema.eid = rset[0][0] |
|
278 else: |
|
279 assert rset |
|
280 |
|
281 def erschema2rql(erschema, groupmap): |
|
282 if isinstance(erschema, schemamod.EntitySchema): |
|
283 return eschema2rql(erschema, groupmap=groupmap) |
|
284 return rschema2rql(erschema, groupmap=groupmap) |
|
285 |
|
286 def specialize2rql(schema): |
|
287 for eschema in schema.entities(): |
|
288 if eschema.final: |
|
289 continue |
|
290 for rql, kwargs in eschemaspecialize2rql(eschema): |
|
291 yield rql, kwargs |
|
292 |
|
293 # etype serialization |
|
294 |
|
295 def eschema2rql(eschema, groupmap=None): |
|
296 """return a list of rql insert statements to enter an entity schema |
|
297 in the database as an CWEType entity |
|
298 """ |
|
299 relations, values = eschema_relations_values(eschema) |
|
300 # NOTE: 'specializes' relation can't be inserted here since there's no |
|
301 # way to make sure the parent type is inserted before the child type |
|
302 yield 'INSERT CWEType X: %s' % ','.join(relations) , values |
|
303 # entity permissions |
|
304 if groupmap is not None: |
|
305 for rql, args in _erperms2rql(eschema, groupmap): |
|
306 yield rql, args |
|
307 |
|
308 def eschema_relations_values(eschema): |
|
309 values = _ervalues(eschema) |
|
310 relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)] |
|
311 return relations, values |
|
312 |
|
313 def eschemaspecialize2rql(eschema): |
|
314 specialized_type = eschema.specializes() |
|
315 if specialized_type: |
|
316 values = {'x': eschema.eid, 'et': specialized_type.eid} |
|
317 yield 'SET X specializes ET WHERE X eid %(x)s, ET eid %(et)s', values |
255 |
318 |
256 def _ervalues(erschema): |
319 def _ervalues(erschema): |
257 try: |
320 try: |
258 type_ = unicode(erschema.type) |
321 type_ = unicode(erschema.type) |
259 except UnicodeDecodeError, e: |
322 except UnicodeDecodeError, e: |
283 else: |
359 else: |
284 values['fulltext_container'] = rschema.fulltext_container |
360 values['fulltext_container'] = rschema.fulltext_container |
285 relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)] |
361 relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)] |
286 return relations, values |
362 return relations, values |
287 |
363 |
288 def _rdef_values(objtype, props): |
364 # rdef serialization |
289 amap = {'order': 'ordernum'} |
365 |
|
366 def rdef2rql(rdef, cstrtypemap, groupmap=None): |
|
367 # don't serialize infered relations |
|
368 if rdef.infered: |
|
369 return |
|
370 relations, values = _rdef_values(rdef) |
|
371 relations.append('X relation_type ER,X from_entity SE,X to_entity OE') |
|
372 values.update({'se': rdef.subject.eid, 'rt': rdef.rtype.eid, 'oe': rdef.object.eid}) |
|
373 if rdef.final: |
|
374 etype = 'CWAttribute' |
|
375 else: |
|
376 etype = 'CWRelation' |
|
377 yield 'INSERT %s X: %s WHERE SE eid %%(se)s,ER eid %%(rt)s,OE eid %%(oe)s' % ( |
|
378 etype, ','.join(relations), ), values |
|
379 for rql, values in constraints2rql(cstrtypemap, rdef.constraints): |
|
380 yield rql, values |
|
381 # no groupmap means "no security insertion" |
|
382 if groupmap: |
|
383 for rql, args in _erperms2rql(rdef, groupmap): |
|
384 yield rql, args |
|
385 |
|
386 def _rdef_values(rdef): |
|
387 amap = {'order': 'ordernum', 'default': 'defaultval'} |
290 values = {} |
388 values = {} |
291 for prop, default in schemamod.RelationDefinitionSchema.rproperty_defs(objtype).iteritems(): |
389 for prop, default in rdef.rproperty_defs(rdef.object).iteritems(): |
292 if prop in ('eid', 'constraints', 'uid', 'infered', 'permissions'): |
390 if prop in ('eid', 'constraints', 'uid', 'infered', 'permissions'): |
293 continue |
391 continue |
294 value = props.get(prop, default) |
392 value = getattr(rdef, prop) |
|
393 # XXX type cast really necessary? |
295 if prop in ('indexed', 'fulltextindexed', 'internationalizable'): |
394 if prop in ('indexed', 'fulltextindexed', 'internationalizable'): |
296 value = bool(value) |
395 value = bool(value) |
297 elif prop == 'ordernum': |
396 elif prop == 'ordernum': |
298 value = int(value) |
397 value = int(value) |
299 elif isinstance(value, str): |
398 elif isinstance(value, str): |
300 value = unicode(value) |
399 value = unicode(value) |
|
400 if value is not None and prop == 'default': |
|
401 if value is False: |
|
402 value = u'' |
|
403 if not isinstance(value, unicode): |
|
404 value = unicode(value) |
301 values[amap.get(prop, prop)] = value |
405 values[amap.get(prop, prop)] = value |
302 return values |
|
303 |
|
304 def nfrdef_relations_values(objtype, props): |
|
305 values = _rdef_values(objtype, props) |
|
306 relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)] |
406 relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)] |
307 return relations, values |
407 return relations, values |
308 |
408 |
309 def frdef_relations_values(objtype, props): |
409 def constraints2rql(cstrtypemap, constraints, rdefeid=None): |
310 values = _rdef_values(objtype, props) |
410 for constraint in constraints: |
311 default = values['default'] |
411 values = {'ct': cstrtypemap[constraint.type()], |
312 del values['default'] |
412 'value': unicode(constraint.serialize()), |
313 if default is not None: |
413 'x': rdefeid} # when not specified, will have to be set by the caller |
314 if default is False: |
414 yield 'INSERT CWConstraint X: X value %(value)s, X cstrtype CT, EDEF constrained_by X WHERE \ |
315 default = u'' |
415 CT eid %(ct)s, EDEF eid %(x)s', values |
316 elif not isinstance(default, unicode): |
|
317 default = unicode(default) |
|
318 values['defaultval'] = default |
|
319 relations = ['X %s %%(%s)s' % (attr, attr) for attr in sorted(values)] |
|
320 return relations, values |
|
321 |
|
322 |
|
323 def __rdef2rql(genmap, rschema, subjtype=None, objtype=None, props=None, |
|
324 groupmap=None): |
|
325 if subjtype is None: |
|
326 assert objtype is None |
|
327 assert props is None |
|
328 targets = sorted(rschema.rdefs) |
|
329 else: |
|
330 assert not objtype is None |
|
331 targets = [(subjtype, objtype)] |
|
332 # relation schema |
|
333 if rschema.final: |
|
334 etype = 'CWAttribute' |
|
335 else: |
|
336 etype = 'CWRelation' |
|
337 for subjtype, objtype in targets: |
|
338 if props is None: |
|
339 _props = rschema.rdef(subjtype, objtype) |
|
340 else: |
|
341 _props = props |
|
342 # don't serialize infered relations |
|
343 if _props.get('infered'): |
|
344 continue |
|
345 gen = genmap[rschema.final] |
|
346 for rql, values in gen(rschema, subjtype, objtype, _props): |
|
347 yield rql, values |
|
348 # no groupmap means "no security insertion" |
|
349 if groupmap: |
|
350 for rql, args in _erperms2rql(_props, groupmap): |
|
351 args['st'] = str(subjtype) |
|
352 args['rt'] = str(rschema) |
|
353 args['ot'] = str(objtype) |
|
354 yield rql + 'X is %s, X from_entity ST, X to_entity OT, '\ |
|
355 'X relation_type RT, RT name %%(rt)s, ST name %%(st)s, '\ |
|
356 'OT name %%(ot)s' % etype, args |
|
357 |
|
358 |
|
359 def schema2rql(schema, skip=None, allow=None): |
|
360 """return a list of rql insert statements to enter the schema in the |
|
361 database as CWRType and CWEType entities |
|
362 """ |
|
363 assert not (skip is not None and allow is not None), \ |
|
364 'can\'t use both skip and allow' |
|
365 all = schema.entities() + schema.relations() |
|
366 if skip is not None: |
|
367 return chain(*[erschema2rql(schema[t]) for t in all if not t in skip]) |
|
368 elif allow is not None: |
|
369 return chain(*[erschema2rql(schema[t]) for t in all if t in allow]) |
|
370 return chain(*[erschema2rql(schema[t]) for t in all]) |
|
371 |
|
372 def erschema2rql(erschema, groupmap): |
|
373 if isinstance(erschema, schemamod.EntitySchema): |
|
374 return eschema2rql(erschema, groupmap=groupmap) |
|
375 return rschema2rql(erschema, groupmap=groupmap) |
|
376 |
|
377 def eschema2rql(eschema, groupmap=None): |
|
378 """return a list of rql insert statements to enter an entity schema |
|
379 in the database as an CWEType entity |
|
380 """ |
|
381 relations, values = eschema_relations_values(eschema) |
|
382 # NOTE: 'specializes' relation can't be inserted here since there's no |
|
383 # way to make sure the parent type is inserted before the child type |
|
384 yield 'INSERT CWEType X: %s' % ','.join(relations) , values |
|
385 # entity permissions |
|
386 if groupmap is not None: |
|
387 for rql, args in _erperms2rql(eschema, groupmap): |
|
388 args['name'] = str(eschema) |
|
389 yield rql + 'X is CWEType, X name %(name)s', args |
|
390 |
|
391 def specialize2rql(schema): |
|
392 for eschema in schema.entities(): |
|
393 for rql, kwargs in eschemaspecialize2rql(eschema): |
|
394 yield rql, kwargs |
|
395 |
|
396 def eschemaspecialize2rql(eschema): |
|
397 specialized_type = eschema.specializes() |
|
398 if specialized_type: |
|
399 values = {'x': eschema.type, 'et': specialized_type.type} |
|
400 yield 'SET X specializes ET WHERE X name %(x)s, ET name %(et)s', values |
|
401 |
|
402 def rschema2rql(rschema, addrdef=True, groupmap=None): |
|
403 """return a list of rql insert statements to enter a relation schema |
|
404 in the database as an CWRType entity |
|
405 """ |
|
406 if rschema.type == 'has_text': |
|
407 return |
|
408 relations, values = rschema_relations_values(rschema) |
|
409 yield 'INSERT CWRType X: %s' % ','.join(relations), values |
|
410 if addrdef: |
|
411 for rql, values in rdef2rql(rschema, groupmap=groupmap): |
|
412 yield rql, values |
|
413 |
|
414 def rdef2rql(rschema, subjtype=None, objtype=None, props=None, groupmap=None): |
|
415 genmap = {True: frdef2rql, False: nfrdef2rql} |
|
416 return __rdef2rql(genmap, rschema, subjtype, objtype, props, groupmap) |
|
417 |
|
418 |
|
419 _LOCATE_RDEF_RQL0 = 'X relation_type ER,X from_entity SE,X to_entity OE' |
|
420 _LOCATE_RDEF_RQL1 = 'SE name %(se)s,ER name %(rt)s,OE name %(oe)s' |
|
421 |
|
422 def frdef2rql(rschema, subjtype, objtype, props): |
|
423 relations, values = frdef_relations_values(objtype, props) |
|
424 relations.append(_LOCATE_RDEF_RQL0) |
|
425 values.update({'se': str(subjtype), 'rt': str(rschema), 'oe': str(objtype)}) |
|
426 yield 'INSERT CWAttribute X: %s WHERE %s' % (','.join(relations), _LOCATE_RDEF_RQL1), values |
|
427 for rql, values in rdefrelations2rql(rschema, subjtype, objtype, props): |
|
428 yield rql + ', EDEF is CWAttribute', values |
|
429 |
|
430 def nfrdef2rql(rschema, subjtype, objtype, props): |
|
431 relations, values = nfrdef_relations_values(objtype, props) |
|
432 relations.append(_LOCATE_RDEF_RQL0) |
|
433 values.update({'se': str(subjtype), 'rt': str(rschema), 'oe': str(objtype)}) |
|
434 yield 'INSERT CWRelation X: %s WHERE %s' % (','.join(relations), _LOCATE_RDEF_RQL1), values |
|
435 for rql, values in rdefrelations2rql(rschema, subjtype, objtype, props): |
|
436 yield rql + ', EDEF is CWRelation', values |
|
437 |
|
438 def rdefrelations2rql(rschema, subjtype, objtype, props): |
|
439 iterators = [] |
|
440 for constraint in props.constraints: |
|
441 iterators.append(constraint2rql(rschema, subjtype, objtype, constraint)) |
|
442 return chain(*iterators) |
|
443 |
|
444 def constraint2rql(rschema, subjtype, objtype, constraint): |
|
445 values = {'ctname': unicode(constraint.type()), |
|
446 'value': unicode(constraint.serialize()), |
|
447 'rt': str(rschema), 'se': str(subjtype), 'oe': str(objtype)} |
|
448 yield 'INSERT CWConstraint X: X value %(value)s, X cstrtype CT, EDEF constrained_by X WHERE \ |
|
449 CT name %(ctname)s, EDEF relation_type ER, EDEF from_entity SE, EDEF to_entity OE, \ |
|
450 ER name %(rt)s, SE name %(se)s, OE name %(oe)s', values |
|
451 |
416 |
452 |
417 |
453 def _erperms2rql(erschema, groupmap): |
418 def _erperms2rql(erschema, groupmap): |
454 """return rql insert statements to enter the entity or relation |
419 """return rql insert statements to enter the entity or relation |
455 schema's permissions in the database as |
420 schema's permissions in the database as |
464 continue |
429 continue |
465 for group_or_rqlexpr in grantedto: |
430 for group_or_rqlexpr in grantedto: |
466 if isinstance(group_or_rqlexpr, basestring): |
431 if isinstance(group_or_rqlexpr, basestring): |
467 # group |
432 # group |
468 try: |
433 try: |
469 yield ('SET X %s_permission Y WHERE Y eid %%(g)s, ' % action, |
434 yield ('SET X %s_permission Y WHERE Y eid %%(g)s, X eid %%(x)s' % action, |
470 {'g': groupmap[group_or_rqlexpr]}) |
435 {'g': groupmap[group_or_rqlexpr]}) |
471 except KeyError: |
436 except KeyError: |
472 continue |
437 continue |
473 else: |
438 else: |
474 # rqlexpr |
439 # rqlexpr |
475 rqlexpr = group_or_rqlexpr |
440 rqlexpr = group_or_rqlexpr |
476 yield ('INSERT RQLExpression E: E expression %%(e)s, E exprtype %%(t)s, ' |
441 yield ('INSERT RQLExpression E: E expression %%(e)s, E exprtype %%(t)s, ' |
477 'E mainvars %%(v)s, X %s_permission E WHERE ' % action, |
442 'E mainvars %%(v)s, X %s_permission E WHERE X eid %%(x)s' % action, |
478 {'e': unicode(rqlexpr.expression), |
443 {'e': unicode(rqlexpr.expression), |
479 'v': unicode(rqlexpr.mainvars), |
444 'v': unicode(rqlexpr.mainvars), |
480 't': unicode(rqlexpr.__class__.__name__)}) |
445 't': unicode(rqlexpr.__class__.__name__)}) |
481 |
446 |
482 |
447 # update functions |
483 def updateeschema2rql(eschema): |
448 |
|
449 def updateeschema2rql(eschema, eid): |
484 relations, values = eschema_relations_values(eschema) |
450 relations, values = eschema_relations_values(eschema) |
485 values['et'] = eschema.type |
451 values['x'] = eid |
486 yield 'SET %s WHERE X is CWEType, X name %%(et)s' % ','.join(relations), values |
452 yield 'SET %s WHERE X eid %%(x)s' % ','.join(relations), values |
487 |
453 |
488 def updaterschema2rql(rschema): |
454 def updaterschema2rql(rschema, eid): |
489 relations, values = rschema_relations_values(rschema) |
455 relations, values = rschema_relations_values(rschema) |
490 values['rt'] = rschema.type |
456 values['x'] = eid |
491 yield 'SET %s WHERE X is CWRType, X name %%(rt)s' % ','.join(relations), values |
457 yield 'SET %s WHERE X eid %%(x)s' % ','.join(relations), values |
492 |
458 |
493 def updaterdef2rql(rschema, subjtype=None, objtype=None, props=None): |
459 def updaterdef2rql(rdef, eid): |
494 genmap = {True: updatefrdef2rql, False: updatenfrdef2rql} |
460 relations, values = _rdef_values(rdef) |
495 return __rdef2rql(genmap, rschema, subjtype, objtype, props) |
461 values['x'] = eid |
496 |
462 yield 'SET %s WHERE X eid %%(x)s' % ','.join(relations), values |
497 def updatefrdef2rql(rschema, subjtype, objtype, props): |
|
498 relations, values = frdef_relations_values(objtype, props) |
|
499 values.update({'se': subjtype, 'rt': str(rschema), 'oe': objtype}) |
|
500 yield 'SET %s WHERE %s, %s, X is CWAttribute' % (','.join(relations), |
|
501 _LOCATE_RDEF_RQL0, |
|
502 _LOCATE_RDEF_RQL1), values |
|
503 |
|
504 def updatenfrdef2rql(rschema, subjtype, objtype, props): |
|
505 relations, values = nfrdef_relations_values(objtype, props) |
|
506 values.update({'se': subjtype, 'rt': str(rschema), 'oe': objtype}) |
|
507 yield 'SET %s WHERE %s, %s, X is CWRelation' % (','.join(relations), |
|
508 _LOCATE_RDEF_RQL0, |
|
509 _LOCATE_RDEF_RQL1), values |
|