mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Fix several problems with the QOF book merge code. Use unique error
codes in the qof_book_merge_commit() function. Fixes 343730. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@16055 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
31ba2398aa
commit
5990e0be74
@ -105,6 +105,8 @@ qof_book_merge_compare(QofBookMergeData *mergeData )
|
||||
gint64 i64Import, i64Target, (*int64_getter) (QofInstance*, QofParam*);
|
||||
gchar charImport, charTarget, (*char_getter) (QofInstance*, QofParam*);
|
||||
|
||||
ENTER (" ");
|
||||
|
||||
g_return_val_if_fail((mergeData != NULL), -1);
|
||||
currentRule = mergeData->currentRule;
|
||||
g_return_val_if_fail((currentRule != NULL), -1);
|
||||
@ -248,6 +250,11 @@ qof_book_merge_compare(QofBookMergeData *mergeData )
|
||||
}
|
||||
if(knowntype == FALSE) {
|
||||
referenceEnt = qtparam->param_getfcn(mergeEnt, qtparam);
|
||||
|
||||
// XXX gncOwner is na object that could be returned, but does not have QofInstance
|
||||
if (safe_strcmp(qtparam->param_type, "gncOwner") == 0)
|
||||
referenceEnt = NULL;
|
||||
|
||||
if((referenceEnt != NULL)
|
||||
&&(safe_strcmp(referenceEnt->e_type, mergeType) == 0)) {
|
||||
currentRule->linkedEntList =
|
||||
@ -263,6 +270,8 @@ qof_book_merge_compare(QofBookMergeData *mergeData )
|
||||
mergeData->currentRule = currentRule;
|
||||
g_free(kvpImport);
|
||||
g_free(kvpTarget);
|
||||
|
||||
LEAVE (" ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -279,10 +288,9 @@ qof_book_merge_commit_foreach_cb(gpointer rule, gpointer arg)
|
||||
}
|
||||
|
||||
static void
|
||||
qof_book_merge_commit_foreach (
|
||||
QofBookMergeRuleForeachCB cb,
|
||||
QofBookMergeResult mergeResult,
|
||||
QofBookMergeData *mergeData)
|
||||
qof_book_merge_commit_foreach (QofBookMergeRuleForeachCB cb,
|
||||
QofBookMergeResult mergeResult,
|
||||
QofBookMergeData *mergeData)
|
||||
{
|
||||
struct QofBookMergeRuleIterate iter;
|
||||
QofBookMergeRule *currentRule;
|
||||
@ -346,7 +354,7 @@ qof_book_merge_rule_cmp(gconstpointer a, gconstpointer b)
|
||||
|
||||
static void
|
||||
qof_book_merge_orphan_check(double difference, QofBookMergeRule *mergeRule,
|
||||
QofBookMergeData *mergeData)
|
||||
QofBookMergeData *mergeData)
|
||||
{
|
||||
/* Called when difference is lower than previous
|
||||
Lookup target to find previous match
|
||||
@ -375,6 +383,8 @@ qof_book_merge_match_orphans(QofBookMergeData *mergeData)
|
||||
QofInstance *best_matchEnt;
|
||||
double difference;
|
||||
|
||||
ENTER (" ");
|
||||
|
||||
g_return_if_fail(mergeData != NULL);
|
||||
currentRule = mergeData->currentRule;
|
||||
g_return_if_fail(currentRule != NULL);
|
||||
@ -406,6 +416,8 @@ qof_book_merge_match_orphans(QofBookMergeData *mergeData)
|
||||
}
|
||||
g_slist_free(mergeData->orphan_list);
|
||||
g_slist_free(targets);
|
||||
|
||||
LEAVE (" ");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -446,13 +458,15 @@ qof_book_merge_foreach ( QofInstance* mergeEnt, gpointer user_data)
|
||||
double difference;
|
||||
GSList *c;
|
||||
|
||||
ENTER (" ");
|
||||
|
||||
g_return_if_fail(user_data != NULL);
|
||||
mergeData = (QofBookMergeData*)user_data;
|
||||
g_return_if_fail(mergeEnt != NULL);
|
||||
currentRule = mergeData->currentRule;
|
||||
g_return_if_fail(currentRule != NULL);
|
||||
g = guid_copy(qof_instance_get_guid(mergeEnt));
|
||||
mergeRule = g_new(QofBookMergeRule,1);
|
||||
mergeRule = g_new0(QofBookMergeRule,1);
|
||||
mergeRule->importEnt = mergeEnt;
|
||||
mergeRule->difference = difference = 0;
|
||||
mergeRule->mergeAbsolute = FALSE;
|
||||
@ -532,6 +546,8 @@ qof_book_merge_foreach ( QofInstance* mergeEnt, gpointer user_data)
|
||||
mergeData->mergeList = g_list_prepend(mergeData->mergeList,mergeRule);
|
||||
guid_free(g);
|
||||
/* return to qof_book_merge_init */
|
||||
|
||||
LEAVE (" ");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -583,17 +599,80 @@ qof_book_merge_rule_cb(gpointer rule, gpointer arg)
|
||||
iter->remainder--;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an object when the MergeResult is MERGE_NEW. Called for each MergeRule.
|
||||
*/
|
||||
static void
|
||||
qof_book_merge_commit_rule_loop(
|
||||
QofBookMergeData *mergeData,
|
||||
QofBookMergeRule *rule,
|
||||
guint remainder)
|
||||
qof_book_merge_commit_rule_create_objects(QofBookMergeData *mergeData,
|
||||
QofBookMergeRule *rule,
|
||||
guint remainder)
|
||||
{
|
||||
QofInstance *inst;
|
||||
|
||||
g_return_if_fail(rule != NULL);
|
||||
g_return_if_fail(mergeData != NULL);
|
||||
g_return_if_fail(mergeData->targetBook != NULL);
|
||||
g_return_if_fail(rule->mergeResult == MERGE_NEW);
|
||||
|
||||
/* The new object takes the GUID from the import to retain an absolute match */
|
||||
inst = qof_object_new_instance(rule->importEnt->e_type, mergeData->targetBook);
|
||||
g_return_if_fail(inst != NULL);
|
||||
rule->targetEnt = inst;
|
||||
qof_instance_copy_guid(rule->targetEnt, rule->importEnt);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the corresponding target entity to the given importEnt
|
||||
*/
|
||||
static QofInstance*
|
||||
qof_book_merge_map_entity(QofBookMergeData *mergeData, QofInstance* importEnt)
|
||||
{
|
||||
QofBookMergeRule *currentRule;
|
||||
GList *node;
|
||||
|
||||
for (node = mergeData->mergeList; node != NULL; node = node->next) {
|
||||
currentRule = node->data;
|
||||
if (currentRule->importEnt == importEnt) {
|
||||
return currentRule->targetEnt;
|
||||
}
|
||||
}
|
||||
PINFO ("qof_book_merge_map_entity: Import Entity not found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
QofBookMergeData *mergeData;
|
||||
QofCollection *mapped_coll;
|
||||
} QofBookMergeMapCollectionIterate;
|
||||
|
||||
|
||||
/**
|
||||
* Map all entities given in importEnt and add them into the mapped_coll
|
||||
*/
|
||||
static void
|
||||
qof_book_merge_map_collection_cb(QofInstance* importEnt, gpointer user_data)
|
||||
{
|
||||
QofBookMergeMapCollectionIterate *mapped_coll_iter;
|
||||
QofInstance *targetEnt;
|
||||
|
||||
mapped_coll_iter = (QofBookMergeMapCollectionIterate*)user_data;
|
||||
targetEnt = qof_book_merge_map_entity(mapped_coll_iter->mergeData, importEnt);
|
||||
qof_collection_add_entity(mapped_coll_iter->mapped_coll, targetEnt);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qof_book_merge_commit_rule_loop(QofBookMergeData *mergeData,
|
||||
QofBookMergeRule *rule,
|
||||
guint remainder)
|
||||
{
|
||||
QofInstance *inst;
|
||||
gboolean registered_type;
|
||||
QofInstance *referenceEnt;
|
||||
/* cm_ prefix used for variables that hold the data to commit */
|
||||
QofCollection *cm_coll;
|
||||
QofCollection *cm_coll, *mapped_coll;
|
||||
QofBookMergeMapCollectionIterate mapped_coll_iter;
|
||||
QofParam *cm_param;
|
||||
gchar *cm_string;
|
||||
const GUID *cm_guid;
|
||||
@ -624,14 +703,15 @@ qof_book_merge_commit_rule_loop(
|
||||
g_return_if_fail(mergeData != NULL);
|
||||
g_return_if_fail(mergeData->targetBook != NULL);
|
||||
g_return_if_fail((rule->mergeResult != MERGE_NEW)||(rule->mergeResult != MERGE_UPDATE));
|
||||
/* create a new object for MERGE_NEW */
|
||||
/* The new object takes the GUID from the import to retain an absolute match */
|
||||
if(rule->mergeResult == MERGE_NEW) {
|
||||
inst = (QofInstance*)qof_object_new_instance(rule->importEnt->e_type, mergeData->targetBook);
|
||||
g_return_if_fail(inst != NULL);
|
||||
rule->targetEnt = inst;
|
||||
qof_instance_set_guid(rule->targetEnt, qof_instance_get_guid(rule->importEnt));
|
||||
}
|
||||
|
||||
DEBUG ("qof_book_merge_commit_rule_loop rule: type: %s, result: %s, importEnt Type: %s, guid: %s",
|
||||
rule->mergeType, rule->mergeResult == MERGE_NEW ? "New" : "Update",
|
||||
rule->importEnt->e_type,
|
||||
guid_to_string(qof_instance_get_guid(rule->importEnt)));
|
||||
DEBUG ("qof_book_merge_commit_rule_loop rule (cont.): targetEnt Type: %s, guid: %s",
|
||||
rule->targetEnt->e_type,
|
||||
guid_to_string(qof_instance_get_guid(rule->targetEnt)));
|
||||
|
||||
/* currentRule->targetEnt is now set,
|
||||
1. by an absolute GUID match or
|
||||
2. by best_matchEnt and difference or
|
||||
@ -642,6 +722,10 @@ qof_book_merge_commit_rule_loop(
|
||||
g_return_if_fail(rule->mergeParam->data);
|
||||
cm_param = rule->mergeParam->data;
|
||||
rule->mergeType = cm_param->param_type;
|
||||
|
||||
DEBUG ("qof_book_merge_commit_rule_loop param: Merge Type: %s, Param Name: %s",
|
||||
rule->mergeType, cm_param->param_name);
|
||||
|
||||
if(safe_strcmp(rule->mergeType, QOF_TYPE_STRING) == 0) {
|
||||
cm_string = cm_param->param_getfcn(rule->importEnt, cm_param);
|
||||
string_setter = (void(*)(QofInstance*, const gchar*))cm_param->param_setfcn;
|
||||
@ -712,12 +796,20 @@ qof_book_merge_commit_rule_loop(
|
||||
}
|
||||
if(safe_strcmp(rule->mergeType, QOF_TYPE_COLLECT) == 0) {
|
||||
cm_coll = cm_param->param_getfcn(rule->importEnt, cm_param);
|
||||
|
||||
/* Created mapped collection */
|
||||
mapped_coll = qof_collection_new(qof_collection_get_type(cm_coll));
|
||||
mapped_coll_iter.mergeData = mergeData;
|
||||
mapped_coll_iter.mapped_coll = mapped_coll;
|
||||
qof_collection_foreach(cm_coll, qof_book_merge_map_collection_cb, &mapped_coll_iter);
|
||||
|
||||
collection_setter = (void(*)(QofInstance*, QofCollection*))cm_param->param_setfcn;
|
||||
if(collection_setter != NULL) { collection_setter(rule->targetEnt, cm_coll); }
|
||||
if(collection_setter != NULL) { collection_setter(rule->targetEnt, mapped_coll); }
|
||||
registered_type = TRUE;
|
||||
}
|
||||
if(safe_strcmp(rule->mergeType, QOF_TYPE_CHOICE) == 0) {
|
||||
referenceEnt = cm_param->param_getfcn(rule->importEnt, cm_param);
|
||||
referenceEnt = qof_book_merge_map_entity(mergeData, referenceEnt);
|
||||
reference_setter = (void(*)(QofInstance*, QofInstance*))cm_param->param_setfcn;
|
||||
if(reference_setter != NULL)
|
||||
{
|
||||
@ -727,6 +819,13 @@ qof_book_merge_commit_rule_loop(
|
||||
}
|
||||
if(registered_type == FALSE) {
|
||||
referenceEnt = cm_param->param_getfcn(rule->importEnt, cm_param);
|
||||
|
||||
// XXX gncOwner is an object that could be returned, but does not have QofInstance
|
||||
if (safe_strcmp(cm_param->param_type, "gncOwner") == 0)
|
||||
referenceEnt = NULL;
|
||||
|
||||
referenceEnt = qof_book_merge_map_entity(mergeData, referenceEnt);
|
||||
|
||||
if(referenceEnt) {
|
||||
reference_setter = (void(*)(QofInstance*, QofInstance*))cm_param->param_setfcn;
|
||||
if(reference_setter != NULL)
|
||||
@ -748,8 +847,10 @@ qof_book_merge_init( QofBook *importBook, QofBook *targetBook)
|
||||
QofBookMergeRule *currentRule;
|
||||
GList *node;
|
||||
|
||||
ENTER (" ");
|
||||
|
||||
g_return_val_if_fail((importBook != NULL)&&(targetBook != NULL), NULL);
|
||||
mergeData = g_new(QofBookMergeData, 1);
|
||||
mergeData = g_new0(QofBookMergeData, 1);
|
||||
mergeData->abort = FALSE;
|
||||
mergeData->mergeList = NULL;
|
||||
mergeData->targetList = NULL;
|
||||
@ -758,7 +859,7 @@ qof_book_merge_init( QofBook *importBook, QofBook *targetBook)
|
||||
mergeData->mergeObjectParams = NULL;
|
||||
mergeData->orphan_list = NULL;
|
||||
mergeData->target_table = g_hash_table_new( g_direct_hash, qof_book_merge_rule_cmp);
|
||||
currentRule = g_new(QofBookMergeRule, 1);
|
||||
currentRule = g_new0(QofBookMergeRule, 1);
|
||||
mergeData->currentRule = currentRule;
|
||||
qof_object_foreach_type(qof_book_merge_foreach_type, mergeData);
|
||||
g_return_val_if_fail(mergeData->mergeObjectParams, NULL);
|
||||
@ -773,6 +874,8 @@ qof_book_merge_init( QofBook *importBook, QofBook *targetBook)
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
LEAVE (" ");
|
||||
return mergeData;
|
||||
}
|
||||
|
||||
@ -899,8 +1002,8 @@ qof_book_merge_param_as_string(QofParam *qtparam, QofInstance *qtEnt)
|
||||
}
|
||||
|
||||
QofBookMergeData*
|
||||
qof_book_merge_update_result(QofBookMergeData *mergeData,
|
||||
QofBookMergeResult tag)
|
||||
qof_book_merge_update_result (QofBookMergeData *mergeData,
|
||||
QofBookMergeResult tag)
|
||||
{
|
||||
QofBookMergeRule *resolved;
|
||||
|
||||
@ -942,14 +1045,17 @@ qof_book_merge_commit(QofBookMergeData *mergeData )
|
||||
QofBookMergeRule *currentRule;
|
||||
GList *check, *node;
|
||||
|
||||
g_return_val_if_fail(mergeData != NULL, -1);
|
||||
g_return_val_if_fail(mergeData->mergeList != NULL, -1);
|
||||
g_return_val_if_fail(mergeData->targetBook != NULL, -1);
|
||||
if(mergeData->abort == TRUE) return -1;
|
||||
ENTER (" ");
|
||||
|
||||
g_return_val_if_fail(mergeData != NULL, -10);
|
||||
g_return_val_if_fail(mergeData->mergeList != NULL, -11);
|
||||
g_return_val_if_fail(mergeData->targetBook != NULL, -12);
|
||||
if(mergeData->abort == TRUE) return -13;
|
||||
check = g_list_copy(mergeData->mergeList);
|
||||
g_return_val_if_fail(check != NULL, -1);
|
||||
g_return_val_if_fail(check != NULL, -14);
|
||||
for (node = check; node != NULL; node = node->next) {
|
||||
currentRule = node->data;
|
||||
|
||||
if(currentRule->mergeResult == MERGE_INVALID) {
|
||||
qof_book_merge_abort(mergeData);
|
||||
g_list_free(check);
|
||||
@ -961,10 +1067,13 @@ qof_book_merge_commit(QofBookMergeData *mergeData )
|
||||
}
|
||||
}
|
||||
g_list_free(check);
|
||||
qof_book_merge_commit_foreach(qof_book_merge_commit_rule_create_objects,
|
||||
MERGE_NEW, mergeData);
|
||||
qof_book_merge_commit_foreach(qof_book_merge_commit_rule_loop,
|
||||
MERGE_NEW, mergeData);
|
||||
qof_book_merge_commit_foreach(qof_book_merge_commit_rule_loop,
|
||||
MERGE_UPDATE, mergeData);
|
||||
|
||||
/* Placeholder for QofObject merge_helper_cb - all objects
|
||||
and all parameters set */
|
||||
while(mergeData->mergeList != NULL) {
|
||||
@ -979,13 +1088,15 @@ qof_book_merge_commit(QofBookMergeData *mergeData )
|
||||
if(mergeData->orphan_list != NULL) { g_slist_free(mergeData->orphan_list); }
|
||||
g_hash_table_destroy(mergeData->target_table);
|
||||
g_free(mergeData);
|
||||
|
||||
LEAVE (" ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
qof_book_merge_rule_foreach(QofBookMergeData *mergeData,
|
||||
QofBookMergeRuleForeachCB cb,
|
||||
QofBookMergeResult mergeResult )
|
||||
qof_book_merge_rule_foreach (QofBookMergeData *mergeData,
|
||||
QofBookMergeRuleForeachCB cb,
|
||||
QofBookMergeResult mergeResult )
|
||||
{
|
||||
struct QofBookMergeRuleIterate iter;
|
||||
QofBookMergeRule *currentRule;
|
||||
|
Loading…
Reference in New Issue
Block a user