diff --git a/python/grass/temporal/abstract_map_dataset.py b/python/grass/temporal/abstract_map_dataset.py index 035e64c7622..6376ded8d8b 100644 --- a/python/grass/temporal/abstract_map_dataset.py +++ b/python/grass/temporal/abstract_map_dataset.py @@ -990,7 +990,7 @@ def delete(self, dbif=None, update=True, execute=True): mapset = get_current_mapset() - dbif, connection_state_changed = init_dbif(dbif) + dbif, connection_state_changed = init_dbif(dbif, only_current_mapset=True) statement = "" if self.is_in_db(dbif, mapset=mapset): @@ -1061,7 +1061,7 @@ def unregister(self, dbif=None, update=True, execute=True): mapset = get_current_mapset() statement = "" - dbif, connection_state_changed = init_dbif(dbif) + dbif, connection_state_changed = init_dbif(dbif, only_current_mapset=True) # Get all datasets in which this map is registered datasets = self.get_registered_stds(dbif, mapset=mapset) diff --git a/python/grass/temporal/base.py b/python/grass/temporal/base.py index 1f2b6290aa6..453b79aef38 100644 --- a/python/grass/temporal/base.py +++ b/python/grass/temporal/base.py @@ -30,6 +30,7 @@ get_tgis_dbmi_paramstyle, SQLDatabaseInterfaceConnection, get_current_mapset, + get_available_temporal_mapsets, ) ############################################################################### @@ -242,12 +243,13 @@ class SQLDatabaseInterface(DictSQLSerializer): """ - def __init__(self, table=None, ident=None): + def __init__(self, table=None, ident=None, tgis_mapset=None): """Constructor of this class :param table: The name of the table :param ident: The identifier (primary key) of this object in the database table + :param tgis_mapset: the mapset to be used for the tgis db """ DictSQLSerializer.__init__(self) @@ -255,10 +257,12 @@ def __init__(self, table=None, ident=None): self.ident = ident self.msgr = get_tgis_message_interface() + # set the mapset where the data are located if self.ident and self.ident.find("@") >= 0: - self.mapset = self.ident.split("@" "")[1] + self.data_mapset = self.ident.split("@" "")[1] else: - self.mapset = None + self.data_mapset = None + self.tgis_mapset = tgis_mapset def get_table_name(self): """Return the name of the table in which the internal @@ -326,19 +330,40 @@ def is_in_db(self, dbif=None, mapset=None): sql = self.get_is_in_db_statement() - # default: search temporal database in the mapset of the map + # determine correct mapset for the temporal database if mapset is None: - mapset = self.mapset + mapset = self.tgis_mapset - if dbif: - dbif.execute(sql, mapset=mapset) - row = dbif.fetchone(mapset=mapset) + row = None + if mapset is not None: + # search only in the tgis db in the given mapset + if dbif: + dbif.execute(sql, mapset=mapset) + row = dbif.fetchone(mapset=mapset) + else: + dbif = SQLDatabaseInterfaceConnection() + dbif.connect() + dbif.execute(sql, mapset=mapset) + row = dbif.fetchone(mapset=mapset) + dbif.close() else: - dbif = SQLDatabaseInterfaceConnection() - dbif.connect() - dbif.execute(sql, mapset=mapset) - row = dbif.fetchone(mapset=mapset) - dbif.close() + # search all available datasets + tgis_mapsets = get_available_temporal_mapsets() + for mapset in tgis_mapsets: + if dbif: + dbif.execute(sql, mapset=mapset) + row = dbif.fetchone(mapset=mapset) + else: + dbif = SQLDatabaseInterfaceConnection() + dbif.connect() + dbif.execute(sql, mapset=mapset) + row = dbif.fetchone(mapset=mapset) + dbif.close() + dbif = None + if row is not None: + # set tgis mapset for this instance + self.tgis_mapset = mapset + break # Nothing found if row is None: @@ -366,7 +391,7 @@ def get_select_statement_mogrified(self, dbif=None): dbif = SQLDatabaseInterfaceConnection() return dbif.mogrify_sql_statement( - self.get_select_statement(), mapset=self.mapset + self.get_select_statement(), mapset=self.tgis_mapset ) def select(self, dbif=None, mapset=None): @@ -377,12 +402,10 @@ def select(self, dbif=None, mapset=None): if None a temporary connection will be established """ sql, args = self.get_select_statement() - # print(sql) - # print(args) - # default: use the temporal database in the mapset of this map + # determine correct mapset for the temporal database if mapset is None: - mapset = self.mapset + mapset = get_current_mapset() self.msgr.debug(2, "SQLDatabaseInterface.select() from mapset %s" % mapset) @@ -442,8 +465,6 @@ def insert(self, dbif=None): if None a temporary connection will be established """ sql, args = self.get_insert_statement() - # print(sql) - # print(args) # use the temporal database in the current mapset mapset = get_current_mapset() @@ -546,10 +567,14 @@ def get_update_all_statement_mogrified(self, dbif=None, ident=None): :param ident: The identifier to be updated, useful for renaming :return: The UPDATE string """ + + # use the temporal database in the current mapset + mapset = get_current_mapset() + if not dbif: dbif = SQLDatabaseInterfaceConnection() - return dbif.mogrify_sql_statement(self.get_update_all_statement(ident)) + return dbif.mogrify_sql_statement(self.get_update_all_statement(ident), mapset) def update_all(self, dbif=None, ident=None): """Serialize the content of this object, including None objects, @@ -640,7 +665,7 @@ def __init__( "name@mapset" or "name:layer@mapset" used as as primary key in the temporal database :param name: The name of the map or dataset - :param mapset: The name of the mapset + :param mapset: The name of the mapset where data are stored :param creator: The name of the creator :param ctime: The creation datetime object :param ttype: The temporal type diff --git a/python/grass/temporal/core.py b/python/grass/temporal/core.py index 4b7fe953b51..67cbac4e215 100644 --- a/python/grass/temporal/core.py +++ b/python/grass/temporal/core.py @@ -463,9 +463,11 @@ def stop_subprocesses(): atexit.register(stop_subprocesses) -def get_available_temporal_mapsets(): +def get_available_temporal_mapsets(only_current_mapset=False): """Return a list of of mapset names with temporal database driver and names that are accessible from the current mapset. + Optionally, the list can be restricted to the current mapset + to avoid that temporal databases outside the current mapset are used :returns: A dictionary, mapset names are keys, the tuple (driver, database) are the values @@ -473,7 +475,10 @@ def get_available_temporal_mapsets(): global c_library_interface global message_interface - mapsets = c_library_interface.available_mapsets() + if only_current_mapset: + mapsets = [get_current_mapset()] + else: + mapsets = c_library_interface.available_mapsets() tgis_mapsets = {} @@ -1059,8 +1064,10 @@ def _create_tgis_metadata_table(content, dbif=None): class SQLDatabaseInterfaceConnection: - def __init__(self): - self.tgis_mapsets = get_available_temporal_mapsets() + def __init__(self, only_current_mapset=False): + self.tgis_mapsets = get_available_temporal_mapsets( + only_current_mapset=only_current_mapset + ) self.current_mapset = get_current_mapset() self.connections = {} self.connected = False @@ -1587,7 +1594,7 @@ def execute_transaction(self, statement, mapset=None): ############################################################################### -def init_dbif(dbif): +def init_dbif(dbif, only_current_mapset=False): """This method checks if the database interface connection exists, if not a new one will be created, connected and True will be returned. If the database interface exists but is not connected, the connection @@ -1612,7 +1619,7 @@ def init_dbif(dbif): connection_state_changed = False if dbif is None: - dbif = SQLDatabaseInterfaceConnection() + dbif = SQLDatabaseInterfaceConnection(only_current_mapset=only_current_mapset) dbif.connect() connection_state_changed = True elif dbif.is_connected() is False: diff --git a/python/grass/temporal/list_stds.py b/python/grass/temporal/list_stds.py index 785bb9217f6..4f0e602e284 100644 --- a/python/grass/temporal/list_stds.py +++ b/python/grass/temporal/list_stds.py @@ -88,6 +88,7 @@ def get_dataset_list( result = {} + # go through the tgis dbs of all available mapsets for mapset in mapsets.keys(): if temporal_type == "absolute": table = sp.get_type() + "_view_abs_time" @@ -99,15 +100,15 @@ def get_dataset_list( else: sql = "SELECT * FROM " + table + # maps from mapset A can be registered in the tgis db in mapset B: + # do not restrict sql where to mapset = if where: sql += " WHERE " + where - sql += " AND mapset = '%s'" % (mapset) - else: - sql += " WHERE mapset = '%s'" % (mapset) if order: sql += " ORDER BY " + order + # only use the tgis db of mapset 'mapset' dbif.execute(sql, mapset=mapset) rows = dbif.fetchall(mapset=mapset) diff --git a/python/grass/temporal/metadata.py b/python/grass/temporal/metadata.py index b9bd7adcc41..0d619cedeea 100644 --- a/python/grass/temporal/metadata.py +++ b/python/grass/temporal/metadata.py @@ -1409,8 +1409,8 @@ def get_semantic_labels(self): dbif = SQLDatabaseInterfaceConnection() dbif.connect() - dbif.execute(sql, mapset=self.mapset) - rows = dbif.fetchall(mapset=self.mapset) + dbif.execute(sql, mapset=self.tgis_mapset) + rows = dbif.fetchall(mapset=self.tgis_mapset) dbif.close() if rows: diff --git a/python/grass/temporal/open_stds.py b/python/grass/temporal/open_stds.py index 837f1a860a7..c99cda270c8 100644 --- a/python/grass/temporal/open_stds.py +++ b/python/grass/temporal/open_stds.py @@ -49,6 +49,7 @@ def open_old_stds(name, type, dbif=None): mapset = get_current_mapset() else: name, mapset = name.split("@") + semantic_label = None if name.find(".") > -1: try: @@ -75,7 +76,7 @@ def open_old_stds(name, type, dbif=None): dbif, connection_state_changed = init_dbif(dbif) - if not sp.is_in_db(dbif): + if not sp.is_in_db(dbif, mapset=mapset): dbif.close() msgr.fatal( _("Space time %(sp)s dataset <%(id)s> not found") diff --git a/python/grass/temporal/register.py b/python/grass/temporal/register.py index 7514cb33d03..6e2b5f6c533 100644 --- a/python/grass/temporal/register.py +++ b/python/grass/temporal/register.py @@ -118,14 +118,8 @@ def register_maps_in_space_time_dataset( msgr.fatal(_("Please specify %s= or %s=") % ("maps", "file")) # We may need the mapset mapset = get_current_mapset() - dbif, connection_state_changed = init_dbif(None) - - # create new stds only in the current mapset - # remove all connections to any other mapsets - # ugly hack ! - currcon = {} - currcon[mapset] = dbif.connections[mapset] - dbif.connections = currcon + # only use the TGIS db of the current mapset + dbif, connection_state_changed = init_dbif(None, only_current_mapset=True) # The name of the space time dataset is optional if name: @@ -312,7 +306,6 @@ def register_maps_in_space_time_dataset( map.set_time_to_relative() else: map.set_time_to_absolute() - else: is_in_db = True # Check the overwrite flag @@ -348,10 +341,10 @@ def register_maps_in_space_time_dataset( continue # Select information from temporal database - map.select(dbif) + map.select(dbif, mapset) # Save the datasets that must be updated - datasets = map.get_registered_stds(dbif) + datasets = map.get_registered_stds(dbif, mapset) if datasets is not None: for dataset in datasets: if dataset != "": @@ -604,6 +597,7 @@ def register_map_object_list( import copy dbif, connection_state_changed = init_dbif(dbif) + mapset = get_current_mapset() filename = gscript.tempfile(True) file = open(filename, "w") @@ -658,7 +652,7 @@ def register_map_object_list( if map.get_type() == "vector": mod(type="vector", name=map.get_name()) mod.run() - if map.is_in_db(dbif): + if map.is_in_db(dbif, mapset): map.delete(dbif) if connection_state_changed: diff --git a/python/grass/temporal/space_time_datasets.py b/python/grass/temporal/space_time_datasets.py index df1da106e0c..b8e853e2441 100644 --- a/python/grass/temporal/space_time_datasets.py +++ b/python/grass/temporal/space_time_datasets.py @@ -1265,6 +1265,7 @@ def reset(self, ident): self.relative_time = STRDSRelativeTime(ident=ident) self.spatial_extent = STRDSSpatialExtent(ident=ident) self.metadata = STRDSMetadata(ident=ident) + self.metadata.tgis_mapset = self.get_mapset() ############################################################################### @@ -1391,6 +1392,7 @@ def reset(self, ident): self.relative_time = STR3DSRelativeTime(ident=ident) self.spatial_extent = STR3DSSpatialExtent(ident=ident) self.metadata = STR3DSMetadata(ident=ident) + self.metadata.tgis_mapset = self.get_mapset() ############################################################################### @@ -1500,6 +1502,7 @@ def reset(self, ident): self.relative_time = STVDSRelativeTime(ident=ident) self.spatial_extent = STVDSSpatialExtent(ident=ident) self.metadata = STVDSMetadata(ident=ident) + self.metadata.tgis_mapset = self.get_mapset() ############################################################################### diff --git a/temporal/t.remove/t.remove.py b/temporal/t.remove/t.remove.py index 6122b453f36..08118718c8f 100755 --- a/temporal/t.remove/t.remove.py +++ b/temporal/t.remove/t.remove.py @@ -86,10 +86,13 @@ def main(): if datasets and file: grass.fatal(_("%s= and %s= are mutually exclusive") % ("input", "file")) + mapset = grass.gisenv()["MAPSET"] + # Make sure the temporal database exists tgis.init() - dbif = tgis.SQLDatabaseInterfaceConnection() + # only use the TGIS db of the current mapset + dbif = tgis.SQLDatabaseInterfaceConnection(only_current_mapset=True) dbif.connect() dataset_list = [] @@ -149,7 +152,7 @@ def main(): count = 1 name_list = [] for map in maps: - map.select(dbif) + map.select(dbif, mapset=mapset) # We may have multiple layer for a single map, hence we need # to avoid multiple deletation of the same map, # but the database entries are still present and must be removed @@ -159,12 +162,14 @@ def main(): if clean and force: if map.get_name() not in name_list: name_list.append(str(map.get_name())) + print("get delete statement...") map_statement += map.delete(dbif=dbif, execute=False) + print("got delete statement") count += 1 # Delete every 100 maps if count % 100 == 0: - dbif.execute_transaction(map_statement) + dbif.execute_transaction(map_statement, mapset=mapset) if clean: if type == "strds": remove(type="raster", name=name_list, run_=True) @@ -176,7 +181,7 @@ def main(): name_list = [] if map_statement: - dbif.execute_transaction(map_statement) + dbif.execute_transaction(map_statement, mapset=mapset) if clean and name_list: if type == "strds": remove(type="raster", name=name_list, run_=True) @@ -196,7 +201,7 @@ def main(): ) else: # Execute the collected SQL statenents - dbif.execute_transaction(statement) + dbif.execute_transaction(statement, mapset=mapset) dbif.close() diff --git a/temporal/t.unregister/t.unregister.py b/temporal/t.unregister/t.unregister.py index ec61dfb3129..1d28c6ecd96 100755 --- a/temporal/t.unregister/t.unregister.py +++ b/temporal/t.unregister/t.unregister.py @@ -73,15 +73,9 @@ def main(): mapset = grass.gisenv()["MAPSET"] - dbif = tgis.SQLDatabaseInterfaceConnection() - dbif.connect() - # modify a stds only if it is in the current mapset - # remove all connections to any other mapsets - # ugly hack ! - currcon = {} - currcon[mapset] = dbif.connections[mapset] - dbif.connections = currcon + dbif = tgis.SQLDatabaseInterfaceConnection(only_current_mapset=True) + dbif.connect() # In case a space time dataset is specified if input: