40 from logilab.common.decorators import cached, clear_cache |
40 from logilab.common.decorators import cached, clear_cache |
41 from logilab.common.configuration import Method |
41 from logilab.common.configuration import Method |
42 from logilab.common.shellutils import getlogin |
42 from logilab.common.shellutils import getlogin |
43 from logilab.database import get_db_helper |
43 from logilab.database import get_db_helper |
44 |
44 |
|
45 from yams import schema2sql as y2sql |
|
46 |
45 from cubicweb import UnknownEid, AuthenticationError, ValidationError, Binary |
47 from cubicweb import UnknownEid, AuthenticationError, ValidationError, Binary |
46 from cubicweb import transaction as tx, server, neg_role |
48 from cubicweb import transaction as tx, server, neg_role |
47 from cubicweb.schema import VIRTUAL_RTYPES |
49 from cubicweb.schema import VIRTUAL_RTYPES |
48 from cubicweb.cwconfig import CubicWebNoAppConfiguration |
50 from cubicweb.cwconfig import CubicWebNoAppConfiguration |
49 from cubicweb.server import hook |
51 from cubicweb.server import hook |
125 ' OR '.join(clauses)) |
127 ' OR '.join(clauses)) |
126 else: |
128 else: |
127 restr = '(%s)' % ' OR '.join(clauses) |
129 restr = '(%s)' % ' OR '.join(clauses) |
128 return '%s WHERE %s' % (select, restr) |
130 return '%s WHERE %s' % (select, restr) |
129 |
131 |
|
132 def rdef_table_column(rdef): |
|
133 """return table and column used to store the given relation definition in |
|
134 the database |
|
135 """ |
|
136 return (SQL_PREFIX + str(rdef.subject), |
|
137 SQL_PREFIX + str(rdef.rtype)) |
|
138 |
|
139 def rdef_physical_info(dbhelper, rdef): |
|
140 """return backend type and a boolean flag if NULL values should be allowed |
|
141 for a given relation definition |
|
142 """ |
|
143 coltype = y2sql.type_from_constraints(dbhelper, rdef.object, |
|
144 rdef.constraints, creating=False) |
|
145 allownull = rdef.cardinality[0] != '1' |
|
146 return coltype, allownull |
130 |
147 |
131 class UndoException(Exception): |
148 class UndoException(Exception): |
132 """something went wrong during undoing""" |
149 """something went wrong during undoing""" |
133 |
150 |
134 |
151 |
676 pass |
693 pass |
677 raise |
694 raise |
678 |
695 |
679 # short cut to method requiring advanced db helper usage ################## |
696 # short cut to method requiring advanced db helper usage ################## |
680 |
697 |
|
698 def update_rdef_column(self, session, rdef): |
|
699 """update physical column for a relation definition (final or inlined) |
|
700 """ |
|
701 table, column = rdef_table_column(rdef) |
|
702 coltype, allownull = rdef_physical_info(self.dbhelper, rdef) |
|
703 if not self.dbhelper.alter_column_support: |
|
704 self.error("backend can't alter %s.%s to %s%s", table, column, coltype, |
|
705 not allownull and 'NOT NULL' or '') |
|
706 return |
|
707 self.dbhelper.change_col_type(LogCursor(session.pool[self.uri]), |
|
708 table, column, coltype, allownull) |
|
709 self.info('altered %s.%s: now %s%s', table, column, coltype, |
|
710 not allownull and 'NOT NULL' or '') |
|
711 |
|
712 def update_rdef_null_allowed(self, session, rdef): |
|
713 """update NULL / NOT NULL of physical column for a relation definition |
|
714 (final or inlined) |
|
715 """ |
|
716 if not self.dbhelper.alter_column_support: |
|
717 # not supported (and NOT NULL not set by yams in that case, so no |
|
718 # worry) |
|
719 return |
|
720 table, column = rdef_table_column(rdef) |
|
721 coltype, allownull = rdef_physical_info(self.dbhelper, rdef) |
|
722 self.dbhelper.set_null_allowed(LogCursor(session.pool[self.uri]), |
|
723 table, column, coltype, allownull) |
|
724 |
|
725 def update_rdef_indexed(self, session, rdef): |
|
726 table, column = rdef_table_column(rdef) |
|
727 if rdef.indexed: |
|
728 self.create_index(session, table, column) |
|
729 else: |
|
730 self.drop_index(session, table, column) |
|
731 |
|
732 def update_rdef_unique(self, session, rdef): |
|
733 table, column = rdef_table_column(rdef) |
|
734 if rdef.constraint_by_type('UniqueConstraint'): |
|
735 self.create_index(session, table, column, unique=True) |
|
736 else: |
|
737 self.drop_index(session, table, column, unique=True) |
|
738 |
681 def create_index(self, session, table, column, unique=False): |
739 def create_index(self, session, table, column, unique=False): |
682 cursor = LogCursor(session.pool[self.uri]) |
740 cursor = LogCursor(session.pool[self.uri]) |
683 self.dbhelper.create_index(cursor, table, column, unique) |
741 self.dbhelper.create_index(cursor, table, column, unique) |
684 |
742 |
685 def drop_index(self, session, table, column, unique=False): |
743 def drop_index(self, session, table, column, unique=False): |
686 cursor = LogCursor(session.pool[self.uri]) |
744 cursor = LogCursor(session.pool[self.uri]) |
687 self.dbhelper.drop_index(cursor, table, column, unique) |
745 self.dbhelper.drop_index(cursor, table, column, unique) |
688 |
|
689 def change_col_type(self, session, table, column, coltype, null_allowed): |
|
690 cursor = LogCursor(session.pool[self.uri]) |
|
691 self.dbhelper.change_col_type(cursor, table, column, coltype, null_allowed) |
|
692 |
|
693 def set_null_allowed(self, session, table, column, coltype, null_allowed): |
|
694 cursor = LogCursor(session.pool[self.uri]) |
|
695 self.dbhelper.set_null_allowed(cursor, table, column, coltype, null_allowed) |
|
696 |
746 |
697 # system source interface ################################################# |
747 # system source interface ################################################# |
698 |
748 |
699 def eid_type_source(self, session, eid): |
749 def eid_type_source(self, session, eid): |
700 """return a tuple (type, source, extid) for the entity with id <eid>""" |
750 """return a tuple (type, source, extid) for the entity with id <eid>""" |
1077 entity[rtype] = Binary(value) |
1127 entity[rtype] = Binary(value) |
1078 elif isinstance(value, str): |
1128 elif isinstance(value, str): |
1079 entity[rtype] = unicode(value, session.encoding, 'replace') |
1129 entity[rtype] = unicode(value, session.encoding, 'replace') |
1080 else: |
1130 else: |
1081 entity[rtype] = value |
1131 entity[rtype] = value |
1082 entity.set_eid(eid) |
1132 entity.eid = eid |
1083 session.repo.init_entity_caches(session, entity, self) |
1133 session.repo.init_entity_caches(session, entity, self) |
1084 entity.edited_attributes = set(entity) |
1134 entity.edited_attributes = set(entity) |
1085 entity.check() |
1135 entity._cw_check() |
1086 self.repo.hm.call_hooks('before_add_entity', session, entity=entity) |
1136 self.repo.hm.call_hooks('before_add_entity', session, entity=entity) |
1087 # restore the entity |
1137 # restore the entity |
1088 action.changes['cw_eid'] = eid |
1138 action.changes['cw_eid'] = eid |
1089 sql = self.sqlgen.insert(SQL_PREFIX + etype, action.changes) |
1139 sql = self.sqlgen.insert(SQL_PREFIX + etype, action.changes) |
1090 self.doexec(session, sql, action.changes) |
1140 self.doexec(session, sql, action.changes) |
1147 entity = self.repo.vreg['etypes'].etype_class(etype)(session) |
1197 entity = self.repo.vreg['etypes'].etype_class(etype)(session) |
1148 except Exception: |
1198 except Exception: |
1149 return [session._( |
1199 return [session._( |
1150 "Can't undo creation of entity %(eid)s of type %(etype)s, type " |
1200 "Can't undo creation of entity %(eid)s of type %(etype)s, type " |
1151 "no more supported" % {'eid': eid, 'etype': etype})] |
1201 "no more supported" % {'eid': eid, 'etype': etype})] |
1152 entity.set_eid(eid) |
1202 entity.eid = eid |
1153 # for proper eid/type cache update |
1203 # for proper eid/type cache update |
1154 hook.set_operation(session, 'pendingeids', eid, |
1204 hook.set_operation(session, 'pendingeids', eid, |
1155 CleanupDeletedEidsCacheOp) |
1205 CleanupDeletedEidsCacheOp) |
1156 self.repo.hm.call_hooks('before_delete_entity', session, entity=entity) |
1206 self.repo.hm.call_hooks('before_delete_entity', session, entity=entity) |
1157 # remove is / is_instance_of which are added using sql by hooks, hence |
1207 # remove is / is_instance_of which are added using sql by hooks, hence |