0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1
"""schema hooks:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 2
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 3
- synchronize the living schema object with the persistent schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 4
- perform physical update on the source when necessary
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 5
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 6
checking for schema consistency is done in hooks.py
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 7
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 8
:organization: Logilab
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 9
:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 10
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 11
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 12
__docformat__ = "restructuredtext en"
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 13
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 14
from yams.schema import BASE_TYPES
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 15
from yams.buildobjs import EntityType , RelationType , RelationDefinition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 16
from yams.schema2sql import eschema2sql , rschema2sql , _type_from_constraints
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 17
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 18
from cubicweb import ValidationError , RepositoryError
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 19
from cubicweb.server import schemaserial as ss
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 20
from cubicweb.server.pool import Operation , SingleLastOperation , PreCommitOperation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 21
from cubicweb.server.hookhelper import ( entity_attr , entity_name ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 22
check_internal_entity )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 23
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 24
# core entity and relation types which can't be removed
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 25
CORE_ETYPES = list ( BASE_TYPES ) + [ 'EEType' , 'ERType' , 'EUser' , 'EGroup' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 26
'EConstraint' , 'EFRDef' , 'ENFRDef' ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 27
CORE_RTYPES = [ 'eid' , 'creation_date' , 'modification_date' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 28
'login' , 'upassword' , 'name' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 29
'is' , 'instanceof' , 'owned_by' , 'created_by' , 'in_group' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 30
'relation_type' , 'from_entity' , 'to_entity' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 31
'constrainted_by' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 32
'read_permission' , 'add_permission' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 33
'delete_permission' , 'updated_permission' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 34
]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 35
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 36
def get_constraints ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 37
constraints = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 38
for cstreid in session . query_data ( entity . eid , ()):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 39
cstrent = session . entity ( cstreid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 40
cstr = CONSTRAINTS [ cstrent . type ] . deserialize ( cstrent . value )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 41
cstr . eid = cstreid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 42
constraints . append ( cstr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 43
return constraints
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 44
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 45
def add_inline_relation_column ( session , etype , rtype ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 46
"""add necessary column and index for an inlined relation"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 47
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 48
session . system_sql ( str ( 'ALTER TABLE %s ADD COLUMN %s integer'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 49
% ( etype , rtype )))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 50
session . info ( 'added column %s to table %s ' , rtype , etype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 51
except :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 52
# silent exception here, if this error has not been raised because the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 53
# column already exists, index creation will fail anyway
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 54
session . exception ( 'error while adding column %s to table %s ' , etype , rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 55
# create index before alter table which may expectingly fail during test
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 56
# (sqlite) while index creation should never fail (test for index existence
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 57
# is done by the dbhelper)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 58
session . pool . source ( 'system' ) . create_index ( session , etype , rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 59
session . info ( 'added index on %s ( %s )' , etype , rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 60
session . add_query_data ( 'createdattrs' , ' %s . %s ' % ( etype , rtype ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 61
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 62
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 63
class SchemaOperation ( Operation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 64
"""base class for schema operations"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 65
def __init__ ( self , session , kobj = None , ** kwargs ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 66
self . schema = session . repo . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 67
self . kobj = kobj
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 68
# once Operation.__init__ has been called, event may be triggered, so
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 69
# do this last !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 70
Operation . __init__ ( self , session , ** kwargs )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 71
# every schema operation is triggering a schema update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 72
UpdateSchemaOp ( session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 73
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 74
class EarlySchemaOperation ( SchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 75
def insert_index ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 76
"""schema operation which are inserted at the begining of the queue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 77
(typically to add/remove entity or relation types)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 78
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 79
i = - 1
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 80
for i , op in enumerate ( self . session . pending_operations ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 81
if not isinstance ( op , EarlySchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 82
return i
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 83
return i + 1
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 84
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 85
class UpdateSchemaOp ( SingleLastOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 86
"""the update schema operation:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 87
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 88
special operation which should be called once and after all other schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 89
operations. It will trigger internal structures rebuilding to consider
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 90
schema changes
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 91
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 92
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 93
def __init__ ( self , session ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 94
self . repo = session . repo
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 95
SingleLastOperation . __init__ ( self , session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 96
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 97
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 98
self . repo . set_schema ( self . repo . schema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 99
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 100
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 101
class DropTableOp ( PreCommitOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 102
"""actually remove a database from the application's schema"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 103
def precommit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 104
dropped = self . session . query_data ( 'droppedtables' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 105
default = set (), setdefault = True )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 106
if self . table in dropped :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 107
return # already processed
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 108
dropped . add ( self . table )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 109
self . session . system_sql ( 'DROP TABLE %s ' % self . table )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 110
self . info ( 'dropped table %s ' , self . table )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 111
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 112
class DropColumnOp ( PreCommitOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 113
"""actually remove the attribut's column from entity table in the system
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 114
database
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 115
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 116
def precommit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 117
session , table , column = self . session , self . table , self . column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 118
# drop index if any
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 119
session . pool . source ( 'system' ) . drop_index ( session , table , column )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 120
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 121
session . system_sql ( 'ALTER TABLE %s DROP COLUMN %s '
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 122
% ( table , column ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 123
self . info ( 'dropped column %s from table %s ' , column , table )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 124
except Exception , ex :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 125
# not supported by sqlite for instance
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 126
self . error ( 'error while altering table %s : %s ' , table , ex )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 127
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 128
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 129
# deletion ####################################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 130
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 131
class DeleteEETypeOp ( SchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 132
"""actually remove the entity type from the application's schema"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 133
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 134
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 135
# del_entity_type also removes entity's relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 136
self . schema . del_entity_type ( self . kobj )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 137
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 138
# s/o entity type have already been deleted
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 139
pass
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 140
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 141
def before_del_eetype ( session , eid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 142
"""before deleting a EEType entity:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 143
* check that we don't remove a core entity type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 144
* cascade to delete related EFRDef and ENFRDef entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 145
* instantiate an operation to delete the entity type on commit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 146
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 147
# final entities can't be deleted, don't care about that
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 148
name = check_internal_entity ( session , eid , CORE_ETYPES )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 149
# delete every entities of this type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 150
session . unsafe_execute ( 'DELETE %s X' % name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 151
DropTableOp ( session , table = name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 152
DeleteEETypeOp ( session , name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 153
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 154
def after_del_eetype ( session , eid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 155
# workflow cleanup
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 156
session . execute ( 'DELETE State X WHERE NOT X state_of Y' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 157
session . execute ( 'DELETE Transition X WHERE NOT X transition_of Y' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 158
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 159
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 160
class DeleteERTypeOp ( SchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 161
"""actually remove the relation type from the application's schema"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 162
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 163
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 164
self . schema . del_relation_type ( self . kobj )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 165
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 166
# s/o entity type have already been deleted
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 167
pass
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 168
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 169
def before_del_ertype ( session , eid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 170
"""before deleting a ERType entity:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 171
* check that we don't remove a core relation type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 172
* cascade to delete related EFRDef and ENFRDef entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 173
* instantiate an operation to delete the relation type on commit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 174
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 175
name = check_internal_entity ( session , eid , CORE_RTYPES )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 176
# delete relation definitions using this relation type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 177
session . execute ( 'DELETE EFRDef X WHERE X relation_type Y, Y eid %(x)s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 178
{ 'x' : eid })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 179
session . execute ( 'DELETE ENFRDef X WHERE X relation_type Y, Y eid %(x)s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 180
{ 'x' : eid })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 181
DeleteERTypeOp ( session , name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 182
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 183
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 184
class DelErdefOp ( SchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 185
"""actually remove the relation definition from the application's schema"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 186
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 187
subjtype , rtype , objtype = self . kobj
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 188
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 189
self . schema . del_relation_def ( subjtype , rtype , objtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 190
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 191
# relation type may have been already deleted
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 192
pass
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 193
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 194
def after_del_relation_type ( session , rdefeid , rtype , rteid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 195
"""before deleting a EFRDef or ENFRDef entity:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 196
* if this is a final or inlined relation definition, instantiate an
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 197
operation to drop necessary column, else if this is the last instance
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 198
of a non final relation, instantiate an operation to drop necessary
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 199
table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 200
* instantiate an operation to delete the relation definition on commit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 201
* delete the associated relation type when necessary
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 202
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 203
subjschema , rschema , objschema = session . repo . schema . schema_by_eid ( rdefeid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 204
pendings = session . query_data ( 'pendingeids' , ())
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 205
# first delete existing relation if necessary
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 206
if rschema . is_final ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 207
rdeftype = 'EFRDef'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 208
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 209
rdeftype = 'ENFRDef'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 210
if not ( subjschema . eid in pendings or objschema . eid in pendings ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 211
session . execute ( 'DELETE X %s Y WHERE X is %s , Y is %s '
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 212
% ( rschema , subjschema , objschema ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 213
execute = session . unsafe_execute
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 214
rset = execute ( 'Any COUNT(X) WHERE X is %s , X relation_type R,'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 215
'R eid %% (x)s' % rdeftype , { 'x' : rteid })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 216
lastrel = rset [ 0 ][ 0 ] == 0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 217
# we have to update physical schema systematically for final and inlined
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 218
# relations, but only if it's the last instance for this relation type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 219
# for other relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 220
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 221
if ( rschema . is_final () or rschema . inlined ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 222
rset = execute ( 'Any COUNT(X) WHERE X is %s , X relation_type R, '
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 223
'R eid %% (x)s, X from_entity E, E name %% (name)s'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 224
% rdeftype , { 'x' : rteid , 'name' : str ( subjschema )})
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 225
if rset [ 0 ][ 0 ] == 0 and not subjschema . eid in pendings :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 226
DropColumnOp ( session , table = subjschema . type , column = rschema . type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 227
elif lastrel :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 228
DropTableOp ( session , table = ' %s _relation' % rschema . type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 229
# if this is the last instance, drop associated relation type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 230
if lastrel and not rteid in pendings :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 231
execute ( 'DELETE ERType X WHERE X eid %(x)s ' , { 'x' : rteid }, 'x' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 232
DelErdefOp ( session , ( subjschema , rschema , objschema ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 233
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 234
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 235
# addition ####################################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 236
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 237
class AddEETypeOp ( EarlySchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 238
"""actually add the entity type to the application's schema"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 239
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 240
eschema = self . schema . add_entity_type ( self . kobj )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 241
eschema . eid = self . eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 242
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 243
def before_add_eetype ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 244
"""before adding a EEType entity:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 245
* check that we are not using an existing entity type,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 246
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 247
name = entity [ 'name' ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 248
schema = session . repo . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 249
if name in schema and schema [ name ] . eid is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 250
raise RepositoryError ( 'an entity type %s already exists' % name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 251
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 252
def after_add_eetype ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 253
"""after adding a EEType entity:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 254
* create the necessary table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 255
* set creation_date and modification_date by creating the necessary
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 256
EFRDef entities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 257
* add owned_by relation by creating the necessary ENFRDef entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 258
* register an operation to add the entity type to the application's
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 259
schema on commit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 260
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 261
if entity . get ( 'final' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 262
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 263
schema = session . repo . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 264
name = entity [ 'name' ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 265
etype = EntityType ( name = name , description = entity . get ( 'description' ),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 266
meta = entity . get ( 'meta' )) # don't care about final
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 267
# fake we add it to the schema now to get a correctly initialized schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 268
# but remove it before doing anything more dangerous...
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 269
schema = session . repo . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 270
eschema = schema . add_entity_type ( etype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 271
eschema . set_default_groups ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 272
# generate table sql and rql to add metadata
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 273
tablesql = eschema2sql ( session . pool . source ( 'system' ) . dbhelper , eschema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 274
relrqls = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 275
for rtype in ( 'is' , 'is_instance_of' , 'creation_date' , 'modification_date' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 276
'created_by' , 'owned_by' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 277
rschema = schema [ rtype ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 278
sampletype = rschema . subjects ()[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 279
desttype = rschema . objects ()[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 280
props = rschema . rproperties ( sampletype , desttype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 281
relrqls += list ( ss . rdef2rql ( rschema , name , desttype , props ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 282
# now remove it !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 283
schema . del_entity_type ( name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 284
# create the necessary table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 285
for sql in tablesql . split ( ';' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 286
if sql . strip ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 287
session . system_sql ( sql )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 288
# register operation to modify the schema on commit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 289
# this have to be done before adding other relations definitions
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 290
# or permission settings
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 291
AddEETypeOp ( session , etype , eid = entity . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 292
# add meta creation_date, modification_date and owned_by relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 293
for rql , kwargs in relrqls :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 294
session . execute ( rql , kwargs )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 295
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 296
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 297
class AddERTypeOp ( EarlySchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 298
"""actually add the relation type to the application's schema"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 299
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 300
rschema = self . schema . add_relation_type ( self . kobj )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 301
rschema . set_default_groups ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 302
rschema . eid = self . eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 303
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 304
def before_add_ertype ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 305
"""before adding a ERType entity:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 306
* check that we are not using an existing relation type,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 307
* register an operation to add the relation type to the application's
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 308
schema on commit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 309
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 310
We don't know yeat this point if a table is necessary
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 311
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 312
name = entity [ 'name' ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 313
if name in session . repo . schema . relations ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 314
raise RepositoryError ( 'a relation type %s already exists' % name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 315
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 316
def after_add_ertype ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 317
"""after a ERType entity has been added:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 318
* register an operation to add the relation type to the application's
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 319
schema on commit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 320
We don't know yeat this point if a table is necessary
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 321
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 322
AddERTypeOp ( session , RelationType ( name = entity [ 'name' ],
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 323
description = entity . get ( 'description' ),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 324
meta = entity . get ( 'meta' , False ),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 325
inlined = entity . get ( 'inlined' , False ),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 326
symetric = entity . get ( 'symetric' , False )),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 327
eid = entity . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 328
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 329
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 330
class AddErdefOp ( EarlySchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 331
"""actually add the attribute relation definition to the application's
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 332
schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 333
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 334
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 335
self . schema . add_relation_def ( self . kobj )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 336
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 337
TYPE_CONVERTER = {
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 338
'Boolean' : bool ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 339
'Int' : int ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 340
'Float' : float ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 341
'Password' : str ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 342
'String' : unicode ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 343
'Date' : unicode ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 344
'Datetime' : unicode ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 345
'Time' : unicode ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 346
}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 347
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 348
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 349
class AddEFRDefPreCommitOp ( PreCommitOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 350
"""an attribute relation (EFRDef) has been added:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 351
* add the necessary column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 352
* set default on this column if any and possible
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 353
* register an operation to add the relation definition to the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 354
application's schema on commit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 355
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 356
constraints are handled by specific hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 357
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 358
def precommit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 359
session = self . session
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 360
entity = self . entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 361
fromentity = entity . from_entity [ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 362
relationtype = entity . relation_type [ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 363
session . execute ( 'SET X ordernum Y+1 WHERE X from_entity SE, SE eid %(se)s , X ordernum Y, X ordernum >= %(order)s , NOT X eid %(x)s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 364
{ 'x' : entity . eid , 'se' : fromentity . eid , 'order' : entity . ordernum or 0 })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 365
subj , rtype = str ( fromentity . name ), str ( relationtype . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 366
obj = str ( entity . to_entity [ 0 ] . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 367
# at this point default is a string or None, but we need a correctly
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 368
# typed value
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 369
default = entity . defaultval
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 370
if default is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 371
default = TYPE_CONVERTER [ obj ]( default )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 372
constraints = get_constraints ( session , entity )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 373
rdef = RelationDefinition ( subj , rtype , obj ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 374
cardinality = entity . cardinality ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 375
order = entity . ordernum ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 376
description = entity . description ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 377
default = default ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 378
indexed = entity . indexed ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 379
fulltextindexed = entity . fulltextindexed ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 380
internationalizable = entity . internationalizable ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 381
constraints = constraints ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 382
eid = entity . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 383
sysource = session . pool . source ( 'system' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 384
attrtype = _type_from_constraints ( sysource . dbhelper , rdef . object ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 385
constraints )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 386
# XXX should be moved somehow into lgc.adbh: sqlite doesn't support to
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 387
# add a new column with UNIQUE, it should be added after the ALTER TABLE
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 388
# using ADD INDEX
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 389
if sysource . dbdriver == 'sqlite' and 'UNIQUE' in attrtype :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 390
extra_unique_index = True
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 391
attrtype = attrtype . replace ( ' UNIQUE' , '' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 392
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 393
extra_unique_index = False
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 394
# added some str() wrapping query since some backend (eg psycopg) don't
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 395
# allow unicode queries
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 396
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 397
session . system_sql ( str ( 'ALTER TABLE %s ADD COLUMN %s %s '
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 398
% ( subj , rtype , attrtype )))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 399
self . info ( 'added column %s to table %s ' , rtype , subj )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 400
except Exception , ex :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 401
# the column probably already exists. this occurs when
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 402
# the entity's type has just been added or if the column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 403
# has not been previously dropped
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 404
self . error ( 'error while altering table %s : %s ' , subj , ex )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 405
if extra_unique_index or entity . indexed :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 406
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 407
sysource . create_index ( session , subj , rtype ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 408
unique = extra_unique_index )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 409
except Exception , ex :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 410
self . error ( 'error while creating index for %s . %s : %s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 411
subj , rtype , ex )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 412
# postgres doesn't implement, so do it in two times
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 413
# ALTER TABLE %s ADD COLUMN %s %s SET DEFAULT %s
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 414
if default is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 415
if isinstance ( default , unicode ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 416
default = default . encode ( sysource . encoding )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 417
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 418
session . system_sql ( 'ALTER TABLE %s ALTER COLUMN %s SET DEFAULT '
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 419
' %% (default)s' % ( subj , rtype ),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 420
{ 'default' : default })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 421
except Exception , ex :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 422
# not supported by sqlite for instance
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 423
self . error ( 'error while altering table %s : %s ' , subj , ex )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 424
session . system_sql ( 'UPDATE %s SET %s = %% (default)s' % ( subj , rtype ),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 425
{ 'default' : default })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 426
AddErdefOp ( session , rdef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 427
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 428
def after_add_efrdef ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 429
AddEFRDefPreCommitOp ( session , entity = entity )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 430
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 431
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 432
class AddENFRDefPreCommitOp ( PreCommitOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 433
"""an actual relation has been added:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 434
* if this is an inlined relation, add the necessary column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 435
else if it's the first instance of this relation type, add the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 436
necessary table and set default permissions
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 437
* register an operation to add the relation definition to the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 438
application's schema on commit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 439
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 440
constraints are handled by specific hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 441
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 442
def precommit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 443
session = self . session
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 444
entity = self . entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 445
fromentity = entity . from_entity [ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 446
relationtype = entity . relation_type [ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 447
session . execute ( 'SET X ordernum Y+1 WHERE X from_entity SE, SE eid %(se)s , X ordernum Y, X ordernum >= %(order)s , NOT X eid %(x)s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 448
{ 'x' : entity . eid , 'se' : fromentity . eid , 'order' : entity . ordernum or 0 })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 449
subj , rtype = str ( fromentity . name ), str ( relationtype . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 450
obj = str ( entity . to_entity [ 0 ] . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 451
card = entity . get ( 'cardinality' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 452
rdef = RelationDefinition ( subj , rtype , obj ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 453
cardinality = card ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 454
order = entity . ordernum ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 455
composite = entity . composite ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 456
description = entity . description ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 457
constraints = get_constraints ( session , entity ),
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 458
eid = entity . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 459
schema = session . repo . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 460
rschema = schema . rschema ( rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 461
# this have to be done before permissions setting
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 462
AddErdefOp ( session , rdef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 463
if rschema . inlined :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 464
# need to add a column if the relation is inlined and if this is the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 465
# first occurence of "Subject relation Something" whatever Something
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 466
# and if it has not been added during other event of the same
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 467
# transaction
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 468
key = ' %s . %s ' % ( subj , rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 469
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 470
alreadythere = bool ( rschema . objects ( subj ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 471
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 472
alreadythere = False
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 473
if not ( alreadythere or
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 474
key in session . query_data ( 'createdattrs' , ())):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 475
add_inline_relation_column ( session , subj , rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 476
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 477
# need to create the relation if no relation definition in the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 478
# schema and if it has not been added during other event of the same
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 479
# transaction
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 480
if not ( rschema . subjects () or
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 481
rtype in session . query_data ( 'createdtables' , ())):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 482
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 483
rschema = schema [ rtype ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 484
tablesql = rschema2sql ( rschema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 485
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 486
# fake we add it to the schema now to get a correctly
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 487
# initialized schema but remove it before doing anything
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 488
# more dangerous...
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 489
rschema = schema . add_relation_type ( rdef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 490
tablesql = rschema2sql ( rschema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 491
schema . del_relation_type ( rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 492
# create the necessary table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 493
for sql in tablesql . split ( ';' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 494
if sql . strip ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 495
self . session . system_sql ( sql )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 496
session . add_query_data ( 'createdtables' , rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 497
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 498
def after_add_enfrdef ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 499
AddENFRDefPreCommitOp ( session , entity = entity )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 500
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 501
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 502
# update ######################################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 503
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 504
def check_valid_changes ( session , entity , ro_attrs = ( 'name' , 'final' )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 505
errors = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 506
# don't use getattr(entity, attr), we would get the modified value if any
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 507
for attr in ro_attrs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 508
origval = entity_attr ( session , entity . eid , attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 509
if entity . get ( attr , origval ) != origval :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 510
errors [ attr ] = session . _ ( "can't change the %s attribute" ) % \
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 511
display_name ( session , attr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 512
if errors :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 513
raise ValidationError ( entity . eid , errors )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 514
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 515
def before_update_eetype ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 516
"""check name change, handle final"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 517
check_valid_changes ( session , entity , ro_attrs = ( 'final' ,))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 518
# don't use getattr(entity, attr), we would get the modified value if any
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 519
oldname = entity_attr ( session , entity . eid , 'name' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 520
newname = entity . get ( 'name' , oldname )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 521
if newname . lower () != oldname . lower ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 522
eschema = session . repo . schema [ oldname ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 523
UpdateEntityTypeName ( session , eschema = eschema ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 524
oldname = oldname , newname = newname )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 525
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 526
def before_update_ertype ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 527
"""check name change, handle final"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 528
check_valid_changes ( session , entity )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 529
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 530
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 531
class UpdateEntityTypeName ( SchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 532
"""this operation updates physical storage accordingly"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 533
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 534
def precommit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 535
# we need sql to operate physical changes on the system database
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 536
sqlexec = self . session . system_sql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 537
sqlexec ( 'ALTER TABLE %s RENAME TO %s ' % ( self . oldname , self . newname ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 538
self . info ( 'renamed table %s to %s ' , self . oldname , self . newname )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 539
sqlexec ( 'UPDATE entities SET type= %s WHERE type= %s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 540
( self . newname , self . oldname ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 541
sqlexec ( 'UPDATE deleted_entities SET type= %s WHERE type= %s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 542
( self . newname , self . oldname ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 543
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 544
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 545
self . session . repo . schema . rename_entity_type ( self . oldname , self . newname )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 546
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 547
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 548
class UpdateRdefOp ( SchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 549
"""actually update some properties of a relation definition"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 550
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 551
def precommit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 552
if 'indexed' in self . values :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 553
sysource = self . session . pool . source ( 'system' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 554
table , column = self . kobj [ 0 ], self . rschema . type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 555
if self . values [ 'indexed' ]:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 556
sysource . create_index ( self . session , table , column )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 557
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 558
sysource . drop_index ( self . session , table , column )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 559
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 560
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 561
# structure should be clean, not need to remove entity's relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 562
# at this point
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 563
self . rschema . _rproperties [ self . kobj ] . update ( self . values )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 564
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 565
def after_update_erdef ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 566
desttype = entity . to_entity [ 0 ] . name
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 567
rschema = session . repo . schema [ entity . relation_type [ 0 ] . name ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 568
newvalues = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 569
for prop in rschema . rproperty_defs ( desttype ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 570
if prop == 'constraints' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 571
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 572
if prop == 'order' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 573
prop = 'ordernum'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 574
if prop in entity :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 575
newvalues [ prop ] = entity [ prop ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 576
if newvalues :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 577
subjtype = entity . from_entity [ 0 ] . name
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 578
UpdateRdefOp ( session , ( subjtype , desttype ), rschema = rschema ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 579
values = newvalues )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 580
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 581
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 582
class UpdateRtypeOp ( SchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 583
"""actually update some properties of a relation definition"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 584
def precommit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 585
session = self . session
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 586
rschema = self . rschema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 587
if rschema . is_final () or not 'inlined' in self . values :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 588
return # nothing to do
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 589
inlined = self . values [ 'inlined' ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 590
entity = self . entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 591
if not entity . inlined_changed ( inlined ): # check in-lining is necessary/possible
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 592
return # nothing to do
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 593
# inlined changed, make necessary physical changes!
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 594
sqlexec = self . session . system_sql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 595
rtype = rschema . type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 596
if not inlined :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 597
# need to create the relation if it has not been already done by another
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 598
# event of the same transaction
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 599
if not rschema . type in session . query_data ( 'createdtables' , ()):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 600
tablesql = rschema2sql ( rschema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 601
# create the necessary table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 602
for sql in tablesql . split ( ';' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 603
if sql . strip ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 604
sqlexec ( sql )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 605
session . add_query_data ( 'createdtables' , rschema . type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 606
# copy existant data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 607
for etype in rschema . subjects ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 608
sqlexec ( 'INSERT INTO %s _relation SELECT eid, %s FROM %s WHERE NOT %s IS NULL'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 609
% ( rtype , rtype , etype , rtype ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 610
# drop existant columns
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 611
for etype in rschema . subjects ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 612
DropColumnOp ( session , table = str ( etype ), column = rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 613
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 614
for etype in rschema . subjects ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 615
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 616
add_inline_relation_column ( session , str ( etype ), rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 617
except Exception , ex :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 618
# the column probably already exists. this occurs when
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 619
# the entity's type has just been added or if the column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 620
# has not been previously dropped
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 621
self . error ( 'error while altering table %s : %s ' , etype , ex )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 622
# copy existant data.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 623
# XXX don't use, it's not supported by sqlite (at least at when i tried it)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 624
#sqlexec('UPDATE %(etype)s SET %(rtype)s=eid_to '
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 625
# 'FROM %(rtype)s_relation '
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 626
# 'WHERE %(etype)s.eid=%(rtype)s_relation.eid_from'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 627
# % locals())
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 628
cursor = sqlexec ( 'SELECT eid_from, eid_to FROM %(etype)s , '
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 629
' %(rtype)s _relation WHERE %(etype)s .eid='
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 630
' %(rtype)s _relation.eid_from' % locals ())
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 631
args = [{ 'val' : eid_to , 'x' : eid } for eid , eid_to in cursor . fetchall ()]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 632
if args :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 633
cursor . executemany ( 'UPDATE %s SET %s = %% (val)s WHERE eid= %% (x)s'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 634
% ( etype , rtype ), args )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 635
# drop existant table
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 636
DropTableOp ( session , table = ' %s _relation' % rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 637
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 638
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 639
# structure should be clean, not need to remove entity's relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 640
# at this point
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 641
self . rschema . __dict__ . update ( self . values )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 642
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 643
def after_update_ertype ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 644
rschema = session . repo . schema . rschema ( entity . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 645
newvalues = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 646
for prop in ( 'meta' , 'symetric' , 'inlined' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 647
if prop in entity :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 648
newvalues [ prop ] = entity [ prop ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 649
if newvalues :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 650
UpdateRtypeOp ( session , entity = entity , rschema = rschema , values = newvalues )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 651
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 652
# constraints synchronization #################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 653
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 654
from cubicweb.schema import CONSTRAINTS
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 655
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 656
class ConstraintOp ( SchemaOperation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 657
"""actually update constraint of a relation definition"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 658
def prepare_constraints ( self , rtype , subjtype , objtype ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 659
constraints = rtype . rproperty ( subjtype , objtype , 'constraints' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 660
self . constraints = list ( constraints )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 661
rtype . set_rproperty ( subjtype , objtype , 'constraints' , self . constraints )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 662
return self . constraints
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 663
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 664
def precommit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 665
rdef = self . entity . reverse_constrained_by [ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 666
session = self . session
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 667
# when the relation is added in the same transaction, the constraint object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 668
# is created by AddEN?FRDefPreCommitOp, there is nothing to do here
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 669
if rdef . eid in session . query_data ( 'neweids' , ()):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 670
self . cancelled = True
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 671
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 672
self . cancelled = False
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 673
schema = session . repo . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 674
subjtype , rtype , objtype = schema . schema_by_eid ( rdef . eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 675
self . prepare_constraints ( rtype , subjtype , objtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 676
cstrtype = self . entity . type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 677
self . cstr = rtype . constraint_by_type ( subjtype , objtype , cstrtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 678
self . _cstr = CONSTRAINTS [ cstrtype ] . deserialize ( self . entity . value )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 679
self . _cstr . eid = self . entity . eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 680
# alter the physical schema on size constraint changes
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 681
if self . _cstr . type () == 'SizeConstraint' and (
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 682
self . cstr is None or self . cstr . max != self . _cstr . max ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 683
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 684
session . system_sql ( 'ALTER TABLE %s ALTER COLUMN %s TYPE VARCHAR( %s )'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 685
% ( subjtype , rtype , self . _cstr . max ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 686
self . info ( 'altered column %s of table %s : now VARCHAR( %s )' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 687
rtype , subjtype , self . _cstr . max )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 688
except Exception , ex :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 689
# not supported by sqlite for instance
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 690
self . error ( 'error while altering table %s : %s ' , subjtype , ex )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 691
elif cstrtype == 'UniqueConstraint' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 692
session . pool . source ( 'system' ) . create_index (
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 693
self . session , str ( subjtype ), str ( rtype ), unique = True )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 694
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 695
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 696
if self . cancelled :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 697
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 698
# in-place removing
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 699
if not self . cstr is None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 700
self . constraints . remove ( self . cstr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 701
self . constraints . append ( self . _cstr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 702
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 703
def after_add_econstraint ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 704
ConstraintOp ( session , entity = entity )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 705
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 706
def after_update_econstraint ( session , entity ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 707
ConstraintOp ( session , entity = entity )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 708
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 709
class DelConstraintOp ( ConstraintOp ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 710
"""actually remove a constraint of a relation definition"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 711
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 712
def precommit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 713
self . prepare_constraints ( self . rtype , self . subjtype , self . objtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 714
cstrtype = self . cstr . type ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 715
# alter the physical schema on size/unique constraint changes
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 716
if cstrtype == 'SizeConstraint' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 717
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 718
self . session . system_sql ( 'ALTER TABLE %s ALTER COLUMN %s TYPE TEXT'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 719
% ( self . subjtype , self . rtype ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 720
self . info ( 'altered column %s of table %s : now TEXT' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 721
self . rtype , self . subjtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 722
except Exception , ex :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 723
# not supported by sqlite for instance
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 724
self . error ( 'error while altering table %s : %s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 725
self . subjtype , ex )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 726
elif cstrtype == 'UniqueConstraint' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 727
self . session . pool . source ( 'system' ) . drop_index (
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 728
self . session , str ( self . subjtype ), str ( self . rtype ), unique = True )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 729
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 730
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 731
self . constraints . remove ( self . cstr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 732
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 733
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 734
def before_delete_constrained_by ( session , fromeid , rtype , toeid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 735
if not fromeid in session . query_data ( 'pendingeids' , ()):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 736
schema = session . repo . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 737
entity = session . eid_rset ( toeid ) . get_entity ( 0 , 0 )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 738
subjtype , rtype , objtype = schema . schema_by_eid ( fromeid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 739
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 740
cstr = rtype . constraint_by_type ( subjtype , objtype , entity . cstrtype [ 0 ] . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 741
DelConstraintOp ( session , subjtype = subjtype , rtype = rtype , objtype = objtype ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 742
cstr = cstr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 743
except IndexError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 744
session . critical ( 'constraint type no more accessible' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 745
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 746
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 747
def after_add_constrained_by ( session , fromeid , rtype , toeid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 748
if fromeid in session . query_data ( 'neweids' , ()):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 749
session . add_query_data ( fromeid , toeid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 750
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 751
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 752
# schema permissions synchronization ##########################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 753
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 754
class PermissionOp ( Operation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 755
"""base class to synchronize schema permission definitions"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 756
def __init__ ( self , session , perm , etype_eid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 757
self . perm = perm
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 758
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 759
self . name = entity_name ( session , etype_eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 760
except IndexError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 761
self . error ( 'changing permission of a no more existant type # %s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 762
etype_eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 763
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 764
Operation . __init__ ( self , session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 765
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 766
class AddGroupPermissionOp ( PermissionOp ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 767
"""synchronize schema when a *_permission relation has been added on a group
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 768
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 769
def __init__ ( self , session , perm , etype_eid , group_eid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 770
self . group = entity_name ( session , group_eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 771
PermissionOp . __init__ ( self , session , perm , etype_eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 772
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 773
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 774
"""the observed connections pool has been commited"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 775
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 776
erschema = self . schema [ self . name ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 777
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 778
# duh, schema not found, log error and skip operation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 779
self . error ( 'no schema for %s ' , self . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 780
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 781
groups = list ( erschema . get_groups ( self . perm ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 782
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 783
groups . index ( self . group )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 784
self . warning ( 'group %s already have permission %s on %s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 785
self . group , self . perm , erschema . type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 786
except ValueError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 787
groups . append ( self . group )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 788
erschema . set_groups ( self . perm , groups )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 789
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 790
class AddRQLExpressionPermissionOp ( PermissionOp ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 791
"""synchronize schema when a *_permission relation has been added on a rql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 792
expression
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 793
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 794
def __init__ ( self , session , perm , etype_eid , expression ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 795
self . expr = expression
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 796
PermissionOp . __init__ ( self , session , perm , etype_eid )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 797
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 798
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 799
"""the observed connections pool has been commited"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 800
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 801
erschema = self . schema [ self . name ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 802
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 803
# duh, schema not found, log error and skip operation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 804
self . error ( 'no schema for %s ' , self . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 805
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 806
exprs = list ( erschema . get_rqlexprs ( self . perm ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 807
exprs . append ( erschema . rql_expression ( self . expr ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 808
erschema . set_rqlexprs ( self . perm , exprs )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 809
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 810
def after_add_permission ( session , subject , rtype , object ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 811
"""added entity/relation *_permission, need to update schema"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 812
perm = rtype . split ( '_' , 1 )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 813
if session . describe ( object )[ 0 ] == 'EGroup' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 814
AddGroupPermissionOp ( session , perm , subject , object )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 815
else : # RQLExpression
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 816
expr = session . execute ( 'Any EXPR WHERE X eid %(x)s , X expression EXPR' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 817
{ 'x' : object }, 'x' )[ 0 ][ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 818
AddRQLExpressionPermissionOp ( session , perm , subject , expr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 819
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 820
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 821
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 822
class DelGroupPermissionOp ( AddGroupPermissionOp ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 823
"""synchronize schema when a *_permission relation has been deleted from a group"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 824
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 825
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 826
"""the observed connections pool has been commited"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 827
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 828
erschema = self . schema [ self . name ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 829
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 830
# duh, schema not found, log error and skip operation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 831
self . error ( 'no schema for %s ' , self . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 832
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 833
groups = list ( erschema . get_groups ( self . perm ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 834
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 835
groups . remove ( self . group )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 836
erschema . set_groups ( self . perm , groups )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 837
except ValueError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 838
self . error ( 'can \' t remove permission %s on %s to group %s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 839
self . perm , erschema . type , self . group )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 840
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 841
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 842
class DelRQLExpressionPermissionOp ( AddRQLExpressionPermissionOp ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 843
"""synchronize schema when a *_permission relation has been deleted from an rql expression"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 844
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 845
def commit_event ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 846
"""the observed connections pool has been commited"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 847
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 848
erschema = self . schema [ self . name ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 849
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 850
# duh, schema not found, log error and skip operation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 851
self . error ( 'no schema for %s ' , self . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 852
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 853
rqlexprs = list ( erschema . get_rqlexprs ( self . perm ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 854
for i , rqlexpr in enumerate ( rqlexprs ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 855
if rqlexpr . expression == self . expr :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 856
rqlexprs . pop ( i )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 857
break
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 858
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 859
self . error ( 'can \' t remove permission %s on %s for expression %s ' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 860
self . perm , erschema . type , self . expr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 861
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 862
erschema . set_rqlexprs ( self . perm , rqlexprs )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 863
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 864
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 865
def before_del_permission ( session , subject , rtype , object ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 866
"""delete entity/relation *_permission, need to update schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 867
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 868
skip the operation if the related type is being deleted
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 869
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 870
if subject in session . query_data ( 'pendingeids' , ()):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 871
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 872
perm = rtype . split ( '_' , 1 )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 873
if session . describe ( object )[ 0 ] == 'EGroup' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 874
DelGroupPermissionOp ( session , perm , subject , object )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 875
else : # RQLExpression
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 876
expr = session . execute ( 'Any EXPR WHERE X eid %(x)s , X expression EXPR' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 877
{ 'x' : object }, 'x' )[ 0 ][ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 878
DelRQLExpressionPermissionOp ( session , perm , subject , expr )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 879
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 880
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 881
def rebuild_infered_relations ( session , subject , rtype , object ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 882
# registering a schema operation will trigger a call to
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 883
# repo.set_schema() on commit which will in turn rebuild
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 884
# infered relation definitions
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 885
UpdateSchemaOp ( session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 886
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 887
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 888
def _register_schema_hooks ( hm ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 889
"""register schema related hooks on the hooks manager"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 890
# schema synchronisation #####################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 891
# before/after add
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 892
hm . register_hook ( before_add_eetype , 'before_add_entity' , 'EEType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 893
hm . register_hook ( before_add_ertype , 'before_add_entity' , 'ERType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 894
hm . register_hook ( after_add_eetype , 'after_add_entity' , 'EEType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 895
hm . register_hook ( after_add_ertype , 'after_add_entity' , 'ERType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 896
hm . register_hook ( after_add_efrdef , 'after_add_entity' , 'EFRDef' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 897
hm . register_hook ( after_add_enfrdef , 'after_add_entity' , 'ENFRDef' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 898
# before/after update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 899
hm . register_hook ( before_update_eetype , 'before_update_entity' , 'EEType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 900
hm . register_hook ( before_update_ertype , 'before_update_entity' , 'ERType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 901
hm . register_hook ( after_update_ertype , 'after_update_entity' , 'ERType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 902
hm . register_hook ( after_update_erdef , 'after_update_entity' , 'EFRDef' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 903
hm . register_hook ( after_update_erdef , 'after_update_entity' , 'ENFRDef' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 904
# before/after delete
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 905
hm . register_hook ( before_del_eetype , 'before_delete_entity' , 'EEType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 906
hm . register_hook ( after_del_eetype , 'after_delete_entity' , 'EEType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 907
hm . register_hook ( before_del_ertype , 'before_delete_entity' , 'ERType' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 908
hm . register_hook ( after_del_relation_type , 'after_delete_relation' , 'relation_type' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 909
hm . register_hook ( rebuild_infered_relations , 'after_add_relation' , 'specializes' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 910
hm . register_hook ( rebuild_infered_relations , 'after_delete_relation' , 'specializes' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 911
# constraints synchronization hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 912
hm . register_hook ( after_add_econstraint , 'after_add_entity' , 'EConstraint' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 913
hm . register_hook ( after_update_econstraint , 'after_update_entity' , 'EConstraint' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 914
hm . register_hook ( before_delete_constrained_by , 'before_delete_relation' , 'constrained_by' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 915
hm . register_hook ( after_add_constrained_by , 'after_add_relation' , 'constrained_by' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 916
# permissions synchronisation ################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 917
for perm in ( 'read_permission' , 'add_permission' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 918
'delete_permission' , 'update_permission' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 919
hm . register_hook ( after_add_permission , 'after_add_relation' , perm )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 920
hm . register_hook ( before_del_permission , 'before_delete_relation' , perm )