server/sources/native.py
branchstable
changeset 5994 97c55baefa0c
parent 5982 30985571dbc9
child 6019 373a313ee9ec
equal deleted inserted replaced
5976:00b1b6b906cf 5994:97c55baefa0c
    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
  1235         """
  1285         """
  1236         self.debug('reindexing %r', entity.eid)
  1286         self.debug('reindexing %r', entity.eid)
  1237         try:
  1287         try:
  1238             # use cursor_index_object, not cursor_reindex_object since
  1288             # use cursor_index_object, not cursor_reindex_object since
  1239             # unindexing done in the FTIndexEntityOp
  1289             # unindexing done in the FTIndexEntityOp
  1240             self.dbhelper.cursor_index_object(entity.eid, entity,
  1290             self.dbhelper.cursor_index_object(entity.eid,
       
  1291                                               entity.cw_adapt_to('IFTIndexable'),
  1241                                               session.pool['system'])
  1292                                               session.pool['system'])
  1242         except Exception: # let KeyboardInterrupt / SystemExit propagate
  1293         except Exception: # let KeyboardInterrupt / SystemExit propagate
  1243             self.exception('error while reindexing %s', entity)
  1294             self.exception('error while reindexing %s', entity)
  1244 
  1295 
  1245 
  1296 
  1260             if eid in pendingeids or eid in done:
  1311             if eid in pendingeids or eid in done:
  1261                 # entity added and deleted in the same transaction or already
  1312                 # entity added and deleted in the same transaction or already
  1262                 # processed
  1313                 # processed
  1263                 return
  1314                 return
  1264             done.add(eid)
  1315             done.add(eid)
  1265             for container in session.entity_from_eid(eid).fti_containers():
  1316             iftindexable = session.entity_from_eid(eid).cw_adapt_to('IFTIndexable')
       
  1317             for container in iftindexable.fti_containers():
  1266                 source.fti_unindex_entity(session, container.eid)
  1318                 source.fti_unindex_entity(session, container.eid)
  1267                 source.fti_index_entity(session, container)
  1319                 source.fti_index_entity(session, container)
  1268 
  1320 
  1269 
  1321 
  1270 def sql_schema(driver):
  1322 def sql_schema(driver):