* src/GrampsBSDDB.py (GrampsBSDDBCursor): add delete method;
(GrampsBSDDBDupCursor): Add class to handle duplicates. * src/plugins/Check.py: Avoid cursors when modifying data; (low_level): Add a low level repair routine, bypassing transactions. svn: r5619
This commit is contained in:
parent
be83003e5c
commit
e96641fa81
@ -1,3 +1,9 @@
|
|||||||
|
2005-12-22 Alex Roitman <shura@gramps-project.org>
|
||||||
|
* src/GrampsBSDDB.py (GrampsBSDDBCursor): add delete method;
|
||||||
|
(GrampsBSDDBDupCursor): Add class to handle duplicates.
|
||||||
|
* src/plugins/Check.py: Avoid cursors when modifying data;
|
||||||
|
(low_level): Add a low level repair routine, bypassing transactions.
|
||||||
|
|
||||||
2005-12-21 Don Allingham <don@gramps-project.org>
|
2005-12-21 Don Allingham <don@gramps-project.org>
|
||||||
* src/ReadGedcom.py: handle overlapping on source and family ID values
|
* src/ReadGedcom.py: handle overlapping on source and family ID values
|
||||||
|
|
||||||
|
@ -69,6 +69,18 @@ class GrampsBSDDBCursor(GrampsCursor):
|
|||||||
def close(self):
|
def close(self):
|
||||||
self.cursor.close()
|
self.cursor.close()
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
self.cursor.delete()
|
||||||
|
|
||||||
|
class GrampsBSDDBDupCursor(GrampsBSDDBCursor):
|
||||||
|
"""Cursor that includes handling for duplicate keys"""
|
||||||
|
|
||||||
|
def set(self,key):
|
||||||
|
return self.cursor.set(str(key))
|
||||||
|
|
||||||
|
def next_dup(self):
|
||||||
|
return self.cursor.next_dup()
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# GrampsBSDDB
|
# GrampsBSDDB
|
||||||
|
@ -51,6 +51,79 @@ import const
|
|||||||
import Tool
|
import Tool
|
||||||
from QuestionDialog import OkDialog, MissingMediaDialog
|
from QuestionDialog import OkDialog, MissingMediaDialog
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Low Level repair
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
def low_level(db):
|
||||||
|
"""
|
||||||
|
This is a low-level repair routine.
|
||||||
|
|
||||||
|
It is fixing DB inconsistencies such as duplicates.
|
||||||
|
Returns a (status,name) tuple.
|
||||||
|
The boolean status indicates the success of the procedure.
|
||||||
|
The name indicates the problematic table (empty if status is True).
|
||||||
|
"""
|
||||||
|
|
||||||
|
for the_map in [('Person',db.person_map),
|
||||||
|
('Family',db.family_map),
|
||||||
|
('Event',db.event_map),
|
||||||
|
('Place',db.place_map),
|
||||||
|
('Source',db.source_map),
|
||||||
|
('Media',db.media_map)]:
|
||||||
|
|
||||||
|
print "Low-level repair: table: %s" % the_map[0]
|
||||||
|
if _table_low_level(db,the_map[1]):
|
||||||
|
print "Done."
|
||||||
|
else:
|
||||||
|
print "Low-level repair: Problem with table: %s" % the_map[0]
|
||||||
|
return (False,the_map[0])
|
||||||
|
return (True,'')
|
||||||
|
|
||||||
|
|
||||||
|
def _table_low_level(db,table):
|
||||||
|
"""
|
||||||
|
Low level repair for a given db table.
|
||||||
|
"""
|
||||||
|
handle_list = table.keys()
|
||||||
|
dup_handles = sets.Set(
|
||||||
|
[ handle for handle in handle_list if handle_list.count(handle) > 1 ]
|
||||||
|
)
|
||||||
|
|
||||||
|
if not dup_handles:
|
||||||
|
print " No dupes found for this table"
|
||||||
|
return True
|
||||||
|
|
||||||
|
import GrampsBSDDB
|
||||||
|
table_cursor = GrampsBSDDB.GrampsBSDDBDupCursor(table)
|
||||||
|
for handle in dup_handles:
|
||||||
|
print " Duplicates found for handle: %s" % handle
|
||||||
|
try:
|
||||||
|
ret = table_cursor.set(handle)
|
||||||
|
except:
|
||||||
|
print " Failed setting initial cursor."
|
||||||
|
return False
|
||||||
|
|
||||||
|
for count in range(handle_list.count(handle)-1):
|
||||||
|
try:
|
||||||
|
table_cursor.delete()
|
||||||
|
print " Succesfully deleted dupe #%d" % (count+1)
|
||||||
|
except:
|
||||||
|
print " Failed deleting dupe."
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
ret = table_cursor.next_dup()
|
||||||
|
except:
|
||||||
|
print " Failed moving the cursor."
|
||||||
|
return False
|
||||||
|
|
||||||
|
table_cursor.close()
|
||||||
|
table.sync()
|
||||||
|
return True
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# runTool
|
# runTool
|
||||||
@ -69,6 +142,12 @@ class Check(Tool.Tool):
|
|||||||
# checking of a read only database
|
# checking of a read only database
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# The low-level repair is bypassing the transaction mechanism.
|
||||||
|
# As such, we run it before starting the transaction.
|
||||||
|
# We only do this for the BSDDB backend.
|
||||||
|
if db.__class__.__name__ == 'GrampsBSDDB':
|
||||||
|
low_level(db)
|
||||||
|
|
||||||
trans = db.transaction_begin()
|
trans = db.transaction_begin()
|
||||||
trans.set_batch(True)
|
trans.set_batch(True)
|
||||||
db.disable_signals()
|
db.disable_signals()
|
||||||
@ -137,10 +216,8 @@ class CheckIntegrity:
|
|||||||
self.progress.set_pass(_('Looking for duplicate spouses'),
|
self.progress.set_pass(_('Looking for duplicate spouses'),
|
||||||
self.db.get_number_of_people())
|
self.db.get_number_of_people())
|
||||||
|
|
||||||
cursor = self.db.get_person_cursor()
|
for handle in self.db.person_map.keys():
|
||||||
data = cursor.first()
|
value = self.db.person_map[handle]
|
||||||
while data:
|
|
||||||
(handle,value) = data
|
|
||||||
p = RelLib.Person(value)
|
p = RelLib.Person(value)
|
||||||
splist = p.get_family_handle_list()
|
splist = p.get_family_handle_list()
|
||||||
if len(splist) != len(sets.Set(splist)):
|
if len(splist) != len(sets.Set(splist)):
|
||||||
@ -151,27 +228,21 @@ class CheckIntegrity:
|
|||||||
self.duplicate_links.append((handle,value))
|
self.duplicate_links.append((handle,value))
|
||||||
p.set_family_handle_list(new_list)
|
p.set_family_handle_list(new_list)
|
||||||
self.db.commit_person(p,self.trans)
|
self.db.commit_person(p,self.trans)
|
||||||
data = cursor.next()
|
|
||||||
self.progress.step()
|
self.progress.step()
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
|
|
||||||
def fix_encoding(self):
|
def fix_encoding(self):
|
||||||
self.progress.set_pass(_('Looking for character encoding errors'),
|
self.progress.set_pass(_('Looking for character encoding errors'),
|
||||||
self.db.get_number_of_media_objects())
|
self.db.get_number_of_media_objects())
|
||||||
|
|
||||||
cursor = self.db.get_media_cursor()
|
for handle in self.db.media_map.keys():
|
||||||
value = cursor.first()
|
data = self.db.media_map[handle]
|
||||||
while value:
|
|
||||||
(handle,data) = value
|
|
||||||
if type(data[2]) != unicode or type(data[4]) != unicode:
|
if type(data[2]) != unicode or type(data[4]) != unicode:
|
||||||
obj = self.db.get_object_from_handle(handle)
|
obj = self.db.get_object_from_handle(handle)
|
||||||
obj.path = Utils.fix_encoding( obj.path)
|
obj.path = Utils.fix_encoding( obj.path)
|
||||||
obj.desc = Utils.fix_encoding( obj.desc)
|
obj.desc = Utils.fix_encoding( obj.desc)
|
||||||
self.db.commit_media_object(obj,self.trans)
|
self.db.commit_media_object(obj,self.trans)
|
||||||
self.progress.step()
|
self.progress.step()
|
||||||
value = cursor.next()
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
def check_for_broken_family_links(self):
|
def check_for_broken_family_links(self):
|
||||||
# Check persons referenced by the family objects
|
# Check persons referenced by the family objects
|
||||||
@ -559,11 +630,9 @@ class CheckIntegrity:
|
|||||||
self.progress.set_pass(_('Looking for source reference problems'),
|
self.progress.set_pass(_('Looking for source reference problems'),
|
||||||
total)
|
total)
|
||||||
|
|
||||||
cursor = self.db.get_person_cursor()
|
for handle in self.db.person_map.keys():
|
||||||
data = cursor.first()
|
|
||||||
while data:
|
|
||||||
self.progress.step()
|
self.progress.step()
|
||||||
handle,info = data
|
info = self.db.person_map[handle]
|
||||||
person = RelLib.Person()
|
person = RelLib.Person()
|
||||||
person.unserialize(info)
|
person.unserialize(info)
|
||||||
handle_list = person.get_referenced_handles_recursively()
|
handle_list = person.get_referenced_handles_recursively()
|
||||||
@ -576,14 +645,10 @@ class CheckIntegrity:
|
|||||||
new_bad_handles = [handle for handle in bad_handles if handle
|
new_bad_handles = [handle for handle in bad_handles if handle
|
||||||
not in self.invalid_source_references]
|
not in self.invalid_source_references]
|
||||||
self.invalid_source_references += new_bad_handles
|
self.invalid_source_references += new_bad_handles
|
||||||
data = cursor.next()
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
cursor = self.db.get_family_cursor()
|
for handle in self.db.family_map.keys():
|
||||||
data = cursor.first()
|
|
||||||
while data:
|
|
||||||
self.progress.step()
|
self.progress.step()
|
||||||
handle,info = data
|
info = self.db.family_map[handle]
|
||||||
family = RelLib.Family()
|
family = RelLib.Family()
|
||||||
family.unserialize(info)
|
family.unserialize(info)
|
||||||
handle_list = family.get_referenced_handles_recursively()
|
handle_list = family.get_referenced_handles_recursively()
|
||||||
@ -596,14 +661,10 @@ class CheckIntegrity:
|
|||||||
new_bad_handles = [handle for handle in bad_handles if handle
|
new_bad_handles = [handle for handle in bad_handles if handle
|
||||||
not in self.invalid_source_references]
|
not in self.invalid_source_references]
|
||||||
self.invalid_source_references += new_bad_handles
|
self.invalid_source_references += new_bad_handles
|
||||||
data = cursor.next()
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
cursor = self.db.get_place_cursor()
|
for handle in self.db.place_map.keys():
|
||||||
data = cursor.first()
|
|
||||||
while data:
|
|
||||||
self.progress.step()
|
self.progress.step()
|
||||||
handle,info = data
|
info = self.db.place_map[handle]
|
||||||
place = RelLib.Place()
|
place = RelLib.Place()
|
||||||
place.unserialize(info)
|
place.unserialize(info)
|
||||||
handle_list = place.get_referenced_handles_recursively()
|
handle_list = place.get_referenced_handles_recursively()
|
||||||
@ -612,18 +673,14 @@ class CheckIntegrity:
|
|||||||
item[1] not in known_handles ]
|
item[1] not in known_handles ]
|
||||||
if bad_handles:
|
if bad_handles:
|
||||||
place.remove_source_references(bad_handles)
|
place.remove_source_references(bad_handles)
|
||||||
self.db.commit_family(place,self.trans)
|
self.db.commit_place(place,self.trans)
|
||||||
new_bad_handles = [handle for handle in bad_handles if handle
|
new_bad_handles = [handle for handle in bad_handles if handle
|
||||||
not in self.invalid_source_references]
|
not in self.invalid_source_references]
|
||||||
self.invalid_source_references += new_bad_handles
|
self.invalid_source_references += new_bad_handles
|
||||||
data = cursor.next()
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
cursor = self.db.get_source_cursor()
|
for handle in known_handles:
|
||||||
data = cursor.first()
|
|
||||||
while data:
|
|
||||||
self.progress.step()
|
self.progress.step()
|
||||||
handle,info = data
|
info = self.db.source_map[handle]
|
||||||
source = RelLib.Source()
|
source = RelLib.Source()
|
||||||
source.unserialize(info)
|
source.unserialize(info)
|
||||||
handle_list = source.get_referenced_handles_recursively()
|
handle_list = source.get_referenced_handles_recursively()
|
||||||
@ -636,14 +693,10 @@ class CheckIntegrity:
|
|||||||
new_bad_handles = [handle for handle in bad_handles if handle
|
new_bad_handles = [handle for handle in bad_handles if handle
|
||||||
not in self.invalid_source_references]
|
not in self.invalid_source_references]
|
||||||
self.invalid_source_references += new_bad_handles
|
self.invalid_source_references += new_bad_handles
|
||||||
data = cursor.next()
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
cursor = self.db.get_media_cursor()
|
for handle in self.db.media_map.keys():
|
||||||
data = cursor.first()
|
|
||||||
while data:
|
|
||||||
self.progress.step()
|
self.progress.step()
|
||||||
handle,info = data
|
info = self.db.media_map[handle]
|
||||||
obj = RelLib.MediaObject()
|
obj = RelLib.MediaObject()
|
||||||
obj.unserialize(info)
|
obj.unserialize(info)
|
||||||
handle_list = obj.get_referenced_handles_recursively()
|
handle_list = obj.get_referenced_handles_recursively()
|
||||||
@ -656,14 +709,10 @@ class CheckIntegrity:
|
|||||||
new_bad_handles = [handle for handle in bad_handles if handle
|
new_bad_handles = [handle for handle in bad_handles if handle
|
||||||
not in self.invalid_source_references]
|
not in self.invalid_source_references]
|
||||||
self.invalid_source_references += new_bad_handles
|
self.invalid_source_references += new_bad_handles
|
||||||
data = cursor.next()
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
cursor = self.db.get_event_cursor()
|
for handle in self.db.event_map.keys():
|
||||||
data = cursor.first()
|
|
||||||
while data:
|
|
||||||
self.progress.step()
|
self.progress.step()
|
||||||
handle,info = data
|
info = self.db.event_map[handle]
|
||||||
event = RelLib.Event()
|
event = RelLib.Event()
|
||||||
event.unserialize(info)
|
event.unserialize(info)
|
||||||
handle_list = event.get_referenced_handles_recursively()
|
handle_list = event.get_referenced_handles_recursively()
|
||||||
@ -676,8 +725,6 @@ class CheckIntegrity:
|
|||||||
new_bad_handles = [handle for handle in bad_handles if handle
|
new_bad_handles = [handle for handle in bad_handles if handle
|
||||||
not in self.invalid_source_references]
|
not in self.invalid_source_references]
|
||||||
self.invalid_source_references += new_bad_handles
|
self.invalid_source_references += new_bad_handles
|
||||||
data = cursor.next()
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
def build_report(self,cl=0):
|
def build_report(self,cl=0):
|
||||||
self.progress.close()
|
self.progress.close()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user