177 self.system_source = self.get_source('native', 'system', |
177 self.system_source = self.get_source('native', 'system', |
178 config.system_source_config.copy()) |
178 config.system_source_config.copy()) |
179 self.sources_by_uri = {'system': self.system_source} |
179 self.sources_by_uri = {'system': self.system_source} |
180 # querier helper, need to be created after sources initialization |
180 # querier helper, need to be created after sources initialization |
181 self.querier = querier.QuerierHelper(self, self.schema) |
181 self.querier = querier.QuerierHelper(self, self.schema) |
182 # cache eid -> (type, extid) |
182 # cache eid -> type |
183 self._type_extid_cache = {} |
183 self._type_cache = {} |
184 # cache extid -> eid |
|
185 # open some connection sets |
184 # open some connection sets |
186 if config.init_cnxset_pool: |
185 if config.init_cnxset_pool: |
187 self.init_cnxset_pool() |
186 self.init_cnxset_pool() |
188 # the hooks manager |
187 # the hooks manager |
189 self.hm = hook.HooksManager(self.vreg) |
188 self.hm = hook.HooksManager(self.vreg) |
712 # data sources handling ################################################### |
711 # data sources handling ################################################### |
713 # * correspondance between eid and type |
712 # * correspondance between eid and type |
714 # * correspondance between eid and local id (i.e. specific to a given source) |
713 # * correspondance between eid and local id (i.e. specific to a given source) |
715 |
714 |
716 def clear_caches(self, eids): |
715 def clear_caches(self, eids): |
717 etcache = self._type_extid_cache |
716 etcache = self._type_cache |
718 rqlcache = self.querier._rql_cache |
717 rqlcache = self.querier._rql_cache |
719 for eid in eids: |
718 for eid in eids: |
720 try: |
719 try: |
721 etype, extid = etcache.pop(int(eid)) # may be a string in some cases |
720 etype = etcache.pop(int(eid)) # may be a string in some cases |
722 rqlcache.pop(('%s X WHERE X eid %s' % (etype, eid),), None) |
721 rqlcache.pop(('%s X WHERE X eid %s' % (etype, eid),), None) |
723 except KeyError: |
722 except KeyError: |
724 etype = None |
723 etype = None |
725 rqlcache.pop(('Any X WHERE X eid %s' % eid,), None) |
724 rqlcache.pop(('Any X WHERE X eid %s' % eid,), None) |
726 self.system_source.clear_eid_cache(eid, etype) |
725 self.system_source.clear_eid_cache(eid, etype) |
727 |
726 |
728 def type_and_extid_from_eid(self, eid, cnx): |
727 def type_from_eid(self, eid, cnx): |
729 """Return the type and extid of the entity with id `eid`.""" |
728 """Return the type of the entity with id `eid`""" |
730 try: |
729 try: |
731 eid = int(eid) |
730 eid = int(eid) |
732 except ValueError: |
731 except ValueError: |
733 raise UnknownEid(eid) |
732 raise UnknownEid(eid) |
734 try: |
733 try: |
735 return self._type_extid_cache[eid] |
734 return self._type_cache[eid] |
736 except KeyError: |
735 except KeyError: |
737 etype, extid = self.system_source.eid_type_extid(cnx, eid) |
736 etype = self.system_source.eid_type(cnx, eid) |
738 self._type_extid_cache[eid] = (etype, extid) |
737 self._type_cache[eid] = etype |
739 return etype, extid |
738 return etype |
740 |
|
741 def type_from_eid(self, eid, cnx): |
|
742 """Return the type of the entity with id `eid`""" |
|
743 return self.type_and_extid_from_eid(eid, cnx)[0] |
|
744 |
739 |
745 def querier_cache_key(self, cnx, rql, args, eidkeys): |
740 def querier_cache_key(self, cnx, rql, args, eidkeys): |
746 cachekey = [rql] |
741 cachekey = [rql] |
747 for key in sorted(eidkeys): |
742 for key in sorted(eidkeys): |
748 try: |
743 try: |
755 cachekey.append(etype) |
750 cachekey.append(etype) |
756 # ensure eid is correctly typed in args |
751 # ensure eid is correctly typed in args |
757 args[key] = int(args[key]) |
752 args[key] = int(args[key]) |
758 return tuple(cachekey) |
753 return tuple(cachekey) |
759 |
754 |
760 def add_info(self, cnx, entity, source, extid=None): |
755 def add_info(self, cnx, entity, source): |
761 """add type and source info for an eid into the system table, |
756 """add type and source info for an eid into the system table, |
762 and index the entity with the full text index |
757 and index the entity with the full text index |
763 """ |
758 """ |
764 # begin by inserting eid/type/source/extid into the entities table |
759 # begin by inserting eid/type/source into the entities table |
765 hook.CleanupNewEidsCacheOp.get_instance(cnx).add_data(entity.eid) |
760 hook.CleanupNewEidsCacheOp.get_instance(cnx).add_data(entity.eid) |
766 self.system_source.add_info(cnx, entity, source, extid) |
761 self.system_source.add_info(cnx, entity, source) |
767 |
762 |
768 def _delete_cascade_multi(self, cnx, entities): |
763 def _delete_cascade_multi(self, cnx, entities): |
769 """same as _delete_cascade but accepts a list of entities with |
764 """same as _delete_cascade but accepts a list of entities with |
770 the same etype and belonging to the same source. |
765 the same etype and belonging to the same source. |
771 """ |
766 """ |
802 raise |
797 raise |
803 self.exception('error while cascading delete for entity %s. RQL: %s', |
798 self.exception('error while cascading delete for entity %s. RQL: %s', |
804 entities, rql) |
799 entities, rql) |
805 |
800 |
806 def init_entity_caches(self, cnx, entity, source): |
801 def init_entity_caches(self, cnx, entity, source): |
807 """add entity to connection entities cache and repo's extid cache. |
802 """Add entity to connection entities cache and repo's cache.""" |
808 Return entity's ext id if the source isn't the system source. |
|
809 """ |
|
810 cnx.set_entity_cache(entity) |
803 cnx.set_entity_cache(entity) |
811 if source.uri == 'system': |
804 self._type_cache[entity.eid] = entity.cw_etype |
812 extid = None |
|
813 else: |
|
814 extid = source.get_extid(entity) |
|
815 self._type_extid_cache[entity.eid] = (entity.cw_etype, extid) |
|
816 return extid |
|
817 |
805 |
818 def glob_add_entity(self, cnx, edited): |
806 def glob_add_entity(self, cnx, edited): |
819 """add an entity to the repository |
807 """add an entity to the repository |
820 |
808 |
821 the entity eid should originally be None and a unique eid is assigned to |
809 the entity eid should originally be None and a unique eid is assigned to |
827 entity.cw_edited = edited |
815 entity.cw_edited = edited |
828 source = self.system_source |
816 source = self.system_source |
829 # allocate an eid to the entity before calling hooks |
817 # allocate an eid to the entity before calling hooks |
830 entity.eid = self.system_source.create_eid(cnx) |
818 entity.eid = self.system_source.create_eid(cnx) |
831 # set caches asap |
819 # set caches asap |
832 extid = self.init_entity_caches(cnx, entity, source) |
820 self.init_entity_caches(cnx, entity, source) |
833 if server.DEBUG & server.DBG_REPO: |
821 if server.DEBUG & server.DBG_REPO: |
834 print('ADD entity', self, entity.cw_etype, entity.eid, edited) |
822 print('ADD entity', self, entity.cw_etype, entity.eid, edited) |
835 prefill_entity_caches(entity) |
823 prefill_entity_caches(entity) |
836 self.hm.call_hooks('before_add_entity', cnx, entity=entity) |
824 self.hm.call_hooks('before_add_entity', cnx, entity=entity) |
837 relations = preprocess_inlined_relations(cnx, entity) |
825 relations = preprocess_inlined_relations(cnx, entity) |
838 edited.set_defaults() |
826 edited.set_defaults() |
839 if cnx.is_hook_category_activated('integrity'): |
827 if cnx.is_hook_category_activated('integrity'): |
840 edited.check(creation=True) |
828 edited.check(creation=True) |
841 self.add_info(cnx, entity, source, extid) |
829 self.add_info(cnx, entity, source) |
842 try: |
830 try: |
843 source.add_entity(cnx, entity) |
831 source.add_entity(cnx, entity) |
844 except (UniqueTogetherError, ViolatedConstraint) as exc: |
832 except (UniqueTogetherError, ViolatedConstraint) as exc: |
845 userhdlr = cnx.vreg['adapters'].select( |
833 userhdlr = cnx.vreg['adapters'].select( |
846 'IUserFriendlyError', cnx, entity=entity, exc=exc) |
834 'IUserFriendlyError', cnx, entity=entity, exc=exc) |