From f7ef319bbf4ccbd50b2826882c918e7afe4b85e6 Mon Sep 17 00:00:00 2001 From: Philip Van Hoof Date: Tue, 16 Sep 2014 11:48:40 +0200 Subject: Support for nrl:maxCardinality changing from one to many --- src/libtracker-data/tracker-data-manager.c | 157 +++++++++++++++++++++-------- src/libtracker-data/tracker-property.c | 54 ++++++++++ src/libtracker-data/tracker-property.h | 6 ++ 3 files changed, 177 insertions(+), 40 deletions(-) diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c index 03cb80b4c..93d9ba51e 100644 --- a/src/libtracker-data/tracker-data-manager.c +++ b/src/libtracker-data/tracker-data-manager.c @@ -90,6 +90,11 @@ static Conversion allowed_boolean_conversions[] = { { NULL, NULL } }; +static Conversion allowed_cardinality_conversions[] = { + { "1", NULL }, /* Not filled in apparently also gives 1 */ + { NULL, NULL } +}; + static Conversion allowed_range_conversions[] = { { XSD_PREFIX "integer", XSD_PREFIX "string" }, { XSD_PREFIX "integer", XSD_PREFIX "double" }, @@ -577,6 +582,7 @@ fix_indexed (TrackerProperty *property, } } + static void tracker_data_ontology_load_statement (const gchar *ontology_path, gint subject_id, @@ -645,10 +651,12 @@ tracker_data_ontology_load_statement (const gchar *ontology_path, tracker_property_reset_domain_indexes (property); tracker_property_reset_super_properties (property); tracker_property_set_indexed (property, FALSE); + tracker_property_set_cardinality_changed (property, FALSE); tracker_property_set_secondary_index (property, NULL); tracker_property_set_writeback (property, FALSE); tracker_property_set_is_inverse_functional_property (property, FALSE); tracker_property_set_default_value (property, NULL); + tracker_property_set_multiple_values (property, TRUE); } return; } @@ -661,6 +669,7 @@ tracker_data_ontology_load_statement (const gchar *ontology_path, tracker_property_set_is_new (property, in_update); tracker_property_set_uri (property, subject); tracker_property_set_id (property, subject_id); + tracker_property_set_multiple_values (property, TRUE); tracker_ontologies_add_property (property); tracker_ontologies_add_id_uri_pair (subject_id, subject); @@ -1058,31 +1067,6 @@ tracker_data_ontology_load_statement (const gchar *ontology_path, return; } - /* This doesn't detect removed nrl:maxCardinality situations, it - * only checks whether the existing one got changed. For - * detecting the removal of a nrl:maxCardinality, please check the - * tracker_data_ontology_process_changes_pre_db stuff */ - - is_new = tracker_property_get_is_new (property); - if (is_new != in_update) { - /* Detect unsupported ontology change (this needs a journal replay) */ - if (in_update == TRUE && is_new == FALSE) { - if (check_unsupported_property_value_change (ontology_path, - "nrl:maxCardinality", - subject, - predicate, - object)) { - handle_unsupported_ontology_change (ontology_path, - tracker_property_get_name (property), - "nrl:maxCardinality", - tracker_property_get_multiple_values (property) ? "1" : "0", - (atoi (object) == 1) ? "1" : "0", - error); - return; - } - } - } - if (atoi (object) == 1) { tracker_property_set_multiple_values (property, FALSE); tracker_property_set_last_multiple_values (property, FALSE); @@ -1373,6 +1357,62 @@ check_for_deleted_super_classes (TrackerClass *class, } } +static void +check_for_max_cardinality_change (TrackerProperty *property, + GError **error) +{ + TrackerClass *class; + gchar *query = NULL; + TrackerDBCursor *cursor; + gboolean changed = TRUE; + gboolean orig_multiple_values = tracker_property_get_orig_multiple_values (property); + gboolean new_multiple_values = tracker_property_get_multiple_values (property); + GError *n_error = NULL; + const gchar *ontology_path = "Unknown"; + + if (tracker_property_get_is_new (property) == FALSE && + (orig_multiple_values != new_multiple_values && + orig_multiple_values == TRUE)) { + const gchar *ontology_path = "Unknown"; + const gchar *subject = tracker_property_get_uri (property); + + handle_unsupported_ontology_change (ontology_path, + subject, + "nrl:maxCardinality", "none", "1", + &n_error); + if (n_error) { + g_propagate_error (error, n_error); + return; + } + } else if (tracker_property_get_is_new (property) == FALSE && + orig_multiple_values != new_multiple_values && + orig_multiple_values == FALSE) { + const gchar *subject = tracker_property_get_uri (property); + + if (update_property_value (ontology_path, + "nrl:maxCardinality", + subject, + NRL_PREFIX "maxCardinality", + NULL, allowed_cardinality_conversions, + NULL, property, &n_error)) { + TrackerClass *class; + class = tracker_property_get_domain(property); + + g_debug("Dealth with allowed nrl:maxCardinality change for %s's %s", + tracker_class_get_name(class), + tracker_property_get_name(property)); + + tracker_property_set_db_schema_changed (property, TRUE); + tracker_property_set_cardinality_changed (property, TRUE); + tracker_class_set_db_schema_changed (class, TRUE); + } + + if (n_error) { + g_propagate_error (error, n_error); + return; + } + } +} static void check_for_deleted_super_properties (TrackerProperty *property, @@ -1465,26 +1505,19 @@ tracker_data_ontology_process_changes_pre_db (GPtrArray *seen_classes, if (seen_properties) { for (i = 0; i < seen_properties->len; i++) { GError *n_error = NULL; - TrackerProperty *property = g_ptr_array_index (seen_properties, i); - gboolean last_multiple_values = tracker_property_get_last_multiple_values (property); - check_for_deleted_super_properties (property, &n_error); + check_for_max_cardinality_change (property, &n_error); if (n_error) { g_propagate_error (error, n_error); return; } - if (tracker_property_get_is_new (property) == FALSE && - last_multiple_values != tracker_property_get_multiple_values (property)) { - const gchar *ontology_path = "Unknown"; - const gchar *subject = tracker_property_get_uri (property); + check_for_deleted_super_properties (property, &n_error); - handle_unsupported_ontology_change (ontology_path, - subject, - "nrl:maxCardinality", "1", "0", - error); + if (n_error) { + g_propagate_error (error, n_error); return; } } @@ -1922,7 +1955,7 @@ tracker_data_ontology_process_statement (const gchar *graph, } else if (g_strcmp0 (predicate, RDFS_SUB_PROPERTY_OF) == 0 || g_strcmp0 (predicate, RDFS_DOMAIN) == 0 || g_strcmp0 (predicate, RDFS_RANGE) == 0 || - g_strcmp0 (predicate, NRL_MAX_CARDINALITY) == 0 || + /* g_strcmp0 (predicate, NRL_MAX_CARDINALITY) == 0 || */ g_strcmp0 (predicate, TRACKER_PREFIX "indexed") == 0 || g_strcmp0 (predicate, TRACKER_PREFIX "transient") == 0 || g_strcmp0 (predicate, TRACKER_PREFIX "fulltextIndexed") == 0) { @@ -2394,12 +2427,14 @@ db_get_static_data (TrackerDBInterface *iface, tracker_property_set_is_new_domain_index (property, tracker_ontologies_get_class_by_uri (domain_uri), FALSE); tracker_property_set_is_new (property, FALSE); + tracker_property_set_cardinality_changed (property, FALSE); tracker_property_set_transient (property, transient); tracker_property_set_uri (property, uri); tracker_property_set_id (property, id); tracker_property_set_domain (property, tracker_ontologies_get_class_by_uri (domain_uri)); tracker_property_set_range (property, tracker_ontologies_get_class_by_uri (range_uri)); tracker_property_set_multiple_values (property, multi_valued); + tracker_property_set_orig_multiple_values (property, multi_valued); tracker_property_set_indexed (property, indexed); tracker_property_set_default_value (property, default_value); tracker_property_set_force_journal (property, force_journal); @@ -2563,6 +2598,7 @@ create_decomposed_metadata_property_table (TrackerDBInterface *iface, if (!in_update || (in_update && (tracker_property_get_is_new (property) || tracker_property_get_is_new_domain_index (property, service) || + tracker_property_get_cardinality_changed (property) || tracker_property_get_db_schema_changed (property)))) { if (not_single || tracker_property_get_multiple_values (property)) { GString *sql = NULL; @@ -2576,7 +2612,7 @@ create_decomposed_metadata_property_table (TrackerDBInterface *iface, service_name, field_name); } - if (in_change && !tracker_property_get_is_new (property)) { + if (in_change && !tracker_property_get_is_new (property) && !tracker_property_get_cardinality_changed (property)) { g_debug ("Drop index: DROP INDEX IF EXISTS \"%s_%s_ID\"\nRename: ALTER TABLE \"%s_%s\" RENAME TO \"%s_%s_TEMP\"", service_name, field_name, service_name, field_name, service_name, field_name); @@ -2658,7 +2694,8 @@ create_decomposed_metadata_property_table (TrackerDBInterface *iface, } } - if (in_change && !tracker_property_get_is_new (property) && in_col_sql && sel_col_sql) { + if (in_change && !tracker_property_get_is_new (property) && + !tracker_property_get_cardinality_changed (property) && in_col_sql && sel_col_sql) { gchar *query; query = g_strdup_printf ("INSERT INTO \"%s_%s\"(%s) " @@ -3148,6 +3185,7 @@ create_decomposed_metadata_tables (TrackerDBInterface *iface, } if (in_change && sel_col_sql && in_col_sql) { + guint i; gchar *query; query = g_strdup_printf ("INSERT INTO \"%s\"(%s) " @@ -3163,8 +3201,46 @@ create_decomposed_metadata_tables (TrackerDBInterface *iface, g_propagate_error (error, internal_error); goto error_out; } - + g_free (query); + + for (i = 0; i < n_props; i++) { + property = properties[i]; + + if (tracker_property_get_domain (property) == service && tracker_property_get_cardinality_changed (property)) { + GString *n_sel_col_sql, *n_in_col_sql; + const gchar *field_name = tracker_property_get_name (property); + + n_in_col_sql = g_string_new ("ID"); + n_sel_col_sql = g_string_new ("ID"); + + /* Function does what it must do, so reusable atm */ + range_change_for (property, n_in_col_sql, n_sel_col_sql, field_name); + + /* Columns happen to be the same for decomposed multi-value and single value atm */ + + query = g_strdup_printf ("INSERT INTO \"%s_%s\"(%s) " + "SELECT %s FROM \"%s_TEMP\"", + service_name, field_name, + n_in_col_sql->str, n_sel_col_sql->str, + service_name); + + g_string_free (n_in_col_sql, TRUE); + g_string_free (n_sel_col_sql, TRUE); + + g_debug ("Copy supported nlr:maxCardinality change: %s", query); + + tracker_db_interface_execute_query (iface, &internal_error, "%s", query); + + if (internal_error) { + g_propagate_error (error, internal_error); + goto error_out; + } + + g_free (query); + } + } + g_debug ("Rename (drop): DROP TABLE \"%s_TEMP\"", service_name); tracker_db_interface_execute_query (iface, &internal_error, "DROP TABLE \"%s_TEMP\"", service_name); @@ -3276,6 +3352,7 @@ tracker_data_ontology_import_finished (void) tracker_property_set_is_new_domain_index (properties[i], NULL, FALSE); tracker_property_set_is_new (properties[i], FALSE); tracker_property_set_db_schema_changed (properties[i], FALSE); + tracker_property_set_cardinality_changed (properties[i], FALSE); } } diff --git a/src/libtracker-data/tracker-property.c b/src/libtracker-data/tracker-property.c index f79e2c892..f9b05a0aa 100644 --- a/src/libtracker-data/tracker-property.c +++ b/src/libtracker-data/tracker-property.c @@ -70,6 +70,8 @@ struct _TrackerPropertyPrivate { GArray *super_properties; GArray *domain_indexes; GArray *last_super_properties; + gboolean cardinality_changed; + gboolean orig_multiple_values; }; static void property_finalize (GObject *object); @@ -141,6 +143,7 @@ tracker_property_init (TrackerProperty *property) priv->super_properties = g_array_new (TRUE, TRUE, sizeof (TrackerProperty *)); priv->domain_indexes = g_array_new (TRUE, TRUE, sizeof (TrackerClass *)); priv->last_super_properties = NULL; + priv->cardinality_changed = FALSE; /* Make GET_PRIV working */ property->priv = priv; @@ -548,6 +551,18 @@ tracker_property_get_db_schema_changed (TrackerProperty *property) return priv->db_schema_changed; } +gboolean +tracker_property_get_cardinality_changed (TrackerProperty *property) +{ + TrackerPropertyPrivate *priv; + + g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE); + + priv = GET_PRIV (property); + + return priv->cardinality_changed; +} + gboolean tracker_property_get_multiple_values (TrackerProperty *property) { @@ -587,6 +602,18 @@ tracker_property_get_last_multiple_values (TrackerProperty *property) return priv->last_multiple_values; } +gboolean +tracker_property_get_orig_multiple_values (TrackerProperty *property) +{ + TrackerPropertyPrivate *priv; + + g_return_val_if_fail (TRACKER_IS_PROPERTY (property), FALSE); + + priv = GET_PRIV (property); + + return priv->orig_multiple_values; +} + gboolean tracker_property_get_is_inverse_functional_property (TrackerProperty *property) { @@ -958,6 +985,19 @@ tracker_property_set_db_schema_changed (TrackerProperty *property, priv->db_schema_changed = value; } +void +tracker_property_set_cardinality_changed (TrackerProperty *property, + gboolean value) +{ + TrackerPropertyPrivate *priv; + + g_return_if_fail (TRACKER_IS_PROPERTY (property)); + + priv = GET_PRIV (property); + + priv->cardinality_changed = value; +} + void tracker_property_set_fulltext_indexed (TrackerProperty *property, gboolean value) @@ -997,6 +1037,20 @@ tracker_property_set_last_multiple_values (TrackerProperty *property, priv->last_multiple_values = value; } +void +tracker_property_set_orig_multiple_values (TrackerProperty *property, + gboolean value) +{ + TrackerPropertyPrivate *priv; + + g_return_if_fail (TRACKER_IS_PROPERTY (property)); + + priv = GET_PRIV (property); + + priv->orig_multiple_values = value; +} + + void tracker_property_set_is_inverse_functional_property (TrackerProperty *property, gboolean value) diff --git a/src/libtracker-data/tracker-property.h b/src/libtracker-data/tracker-property.h index c2a75d90a..328d130ee 100644 --- a/src/libtracker-data/tracker-property.h +++ b/src/libtracker-data/tracker-property.h @@ -88,6 +88,7 @@ TrackerProperty * tracker_property_get_secondary_index (TrackerProperty gboolean tracker_property_get_fulltext_indexed (TrackerProperty *property); gboolean tracker_property_get_multiple_values (TrackerProperty *property); gboolean tracker_property_get_last_multiple_values(TrackerProperty *property); +gboolean tracker_property_get_orig_multiple_values(TrackerProperty *property); gboolean tracker_property_get_transient (TrackerProperty *property); gboolean tracker_property_get_is_new (TrackerProperty *property); gboolean tracker_property_get_is_new_domain_index (TrackerProperty *property, @@ -95,6 +96,7 @@ gboolean tracker_property_get_is_new_domain_index (TrackerProperty gboolean tracker_property_get_writeback (TrackerProperty *property); const gchar * tracker_property_get_default_value (TrackerProperty *property); gboolean tracker_property_get_db_schema_changed (TrackerProperty *property); +gboolean tracker_property_get_cardinality_changed (TrackerProperty *property); gboolean tracker_property_get_is_inverse_functional_property (TrackerProperty *property); gboolean tracker_property_get_force_journal (TrackerProperty *property); @@ -124,6 +126,8 @@ void tracker_property_set_multiple_values (TrackerProperty gboolean value); void tracker_property_set_last_multiple_values(TrackerProperty *property, gboolean value); +void tracker_property_set_orig_multiple_values(TrackerProperty *property, + gboolean value); void tracker_property_set_transient (TrackerProperty *property, gboolean value); void tracker_property_set_is_new (TrackerProperty *property, @@ -137,6 +141,8 @@ void tracker_property_set_default_value (TrackerProperty const gchar *value); void tracker_property_set_db_schema_changed (TrackerProperty *property, gboolean value); +void tracker_property_set_cardinality_changed (TrackerProperty *property, + gboolean value); void tracker_property_set_is_inverse_functional_property (TrackerProperty *property, gboolean value); -- cgit v1.2.1