Pārlūkot izejas kodu

Implemented renaming of existing space time datasets

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@53642 15284696-431f-4ddb-bdfa-cd5b030d7da7
Soeren Gebbert 12 gadi atpakaļ
vecāks
revīzija
83416a6717

+ 15 - 12
lib/python/temporal/abstract_dataset.py

@@ -244,7 +244,7 @@ class AbstractDataset(object):
             dbif.close()
             dbif.close()
         return statement
         return statement
 
 
-    def update(self, dbif=None, execute=True):
+    def update(self, dbif=None, execute=True, ident=None):
         """!Update temporal dataset entry of database from the internal structure
         """!Update temporal dataset entry of database from the internal structure
            excluding None variables
            excluding None variables
 
 
@@ -252,20 +252,22 @@ class AbstractDataset(object):
            @param execute: If True the SQL statements will be executed.
            @param execute: If True the SQL statements will be executed.
                            If False the prepared SQL statements are returned 
                            If False the prepared SQL statements are returned 
                            and must be executed by the caller.
                            and must be executed by the caller.
+           @param ident: The identifier to be updated, useful for renaming
         """
         """
 
 
         dbif, connect = init_dbif(dbif)
         dbif, connect = init_dbif(dbif)
 
 
         # Build the UPDATE SQL statement
         # Build the UPDATE SQL statement
-        statement = self.base.get_update_statement_mogrified(dbif)
+        statement = self.base.get_update_statement_mogrified(dbif, ident)
         if self.is_time_absolute():
         if self.is_time_absolute():
             statement += self.absolute_time.get_update_statement_mogrified(
             statement += self.absolute_time.get_update_statement_mogrified(
-                dbif)
+                dbif, ident)
         if self.is_time_relative():
         if self.is_time_relative():
             statement += self.relative_time.get_update_statement_mogrified(
             statement += self.relative_time.get_update_statement_mogrified(
-                dbif)
-        statement += self.spatial_extent.get_update_statement_mogrified(dbif)
-        statement += self.metadata.get_update_statement_mogrified(dbif)
+                dbif, ident)
+        statement += self.spatial_extent.get_update_statement_mogrified(dbif, 
+                                                                        ident)
+        statement += self.metadata.get_update_statement_mogrified(dbif, ident)
 
 
         if execute:
         if execute:
             dbif.execute_transaction(statement)
             dbif.execute_transaction(statement)
@@ -277,7 +279,7 @@ class AbstractDataset(object):
             dbif.close()
             dbif.close()
         return statement
         return statement
 
 
-    def update_all(self, dbif=None, execute=True):
+    def update_all(self, dbif=None, execute=True, ident=None):
         """!Update temporal dataset entry of database from the internal structure
         """!Update temporal dataset entry of database from the internal structure
            and include None variables.
            and include None variables.
 
 
@@ -285,21 +287,22 @@ class AbstractDataset(object):
            @param execute: If True the SQL statements will be executed.
            @param execute: If True the SQL statements will be executed.
                            If False the prepared SQL statements are returned 
                            If False the prepared SQL statements are returned 
                            and must be executed by the caller.
                            and must be executed by the caller.
+           @param ident: The identifier to be updated, useful for renaming
         """
         """
 
 
         dbif, connect = init_dbif(dbif)
         dbif, connect = init_dbif(dbif)
 
 
         # Build the UPDATE SQL statement
         # Build the UPDATE SQL statement
-        statement = self.base.get_update_all_statement_mogrified(dbif)
+        statement = self.base.get_update_all_statement_mogrified(dbif, ident)
         if self.is_time_absolute():
         if self.is_time_absolute():
             statement += self.absolute_time.get_update_all_statement_mogrified(
             statement += self.absolute_time.get_update_all_statement_mogrified(
-                dbif)
+                dbif, ident)
         if self.is_time_relative():
         if self.is_time_relative():
             statement += self.relative_time.get_update_all_statement_mogrified(
             statement += self.relative_time.get_update_all_statement_mogrified(
-                dbif)
+                dbif, ident)
         statement += self.spatial_extent.get_update_all_statement_mogrified(
         statement += self.spatial_extent.get_update_all_statement_mogrified(
-            dbif)
-        statement += self.metadata.get_update_all_statement_mogrified(dbif)
+            dbif, ident)
+        statement += self.metadata.get_update_all_statement_mogrified(dbif, ident)
 
 
         if execute:
         if execute:
             dbif.execute_transaction(statement)
             dbif.execute_transaction(statement)

+ 101 - 13
lib/python/temporal/abstract_space_time_dataset.py

@@ -45,6 +45,19 @@ class AbstractSpaceTimeDataset(AbstractDataset):
         raise ImplementationError(
         raise ImplementationError(
             "This method must be implemented in the subclasses")
             "This method must be implemented in the subclasses")
 
 
+    def create_map_register_name(self):
+        """!Create the name of the map register table of this space time dataset
+        
+            The name, mapset and the map type are used to create the table name.
+            
+            ATTENTION: It must be assured that the base object has selected its 
+            content from the database.
+        """
+        
+        return self.base.get_name() + "_" + \
+                self.base.get_mapset() + "_" + \
+                self.get_new_map_instance(None).get_type() + "_register"
+
     def get_map_register(self):
     def get_map_register(self):
         """!Return the name of the map register table"""
         """!Return the name of the map register table"""
         raise ImplementationError(
         raise ImplementationError(
@@ -610,9 +623,6 @@ class AbstractSpaceTimeDataset(AbstractDataset):
            A valid temporal topology (no overlapping or inclusion allowed) 
            A valid temporal topology (no overlapping or inclusion allowed) 
            is needed to get correct results.
            is needed to get correct results.
 
 
-           The dataset must have "interval" as temporal map type, 
-           so all maps have valid interval time.
-
            Gaps between maps are identified as unregistered maps with id==None.
            Gaps between maps are identified as unregistered maps with id==None.
 
 
            The objects are initialized with the id and the temporal 
            The objects are initialized with the id and the temporal 
@@ -629,12 +639,6 @@ class AbstractSpaceTimeDataset(AbstractDataset):
         dbif, connect = init_dbif(dbif)
         dbif, connect = init_dbif(dbif)
 
 
         obj_list = []
         obj_list = []
-        
-        if self.get_map_time() == "point" or self.get_map_time() == "mixed":
-            core.error(_("The space time %(type)s dataset <%(name)s> must have"
-                         " interval time"%\
-                         {"type":self.get_new_map_instance(None).get_type(),
-                          "name":self.get_id()}))
 
 
         if gran is None:
         if gran is None:
             gran = self.get_granularity()
             gran = self.get_granularity()
@@ -651,6 +655,8 @@ class AbstractSpaceTimeDataset(AbstractDataset):
 
 
             rows = self.get_registered_maps("id", where, "start_time", dbif)
             rows = self.get_registered_maps("id", where, "start_time", dbif)
 
 
+            found_gap = False
+            
             if rows is not None and len(rows) != 0:
             if rows is not None and len(rows) != 0:
                 if len(rows) > 1:
                 if len(rows) > 1:
                     core.warning(_("More than one map found in a granule. "
                     core.warning(_("More than one map found in a granule. "
@@ -673,8 +679,39 @@ class AbstractSpaceTimeDataset(AbstractDataset):
                     maplist.append(copy.copy(map))
                     maplist.append(copy.copy(map))
 
 
                 obj_list.append(copy.copy(maplist))
                 obj_list.append(copy.copy(maplist))
-	    else:
-		# Found a gap
+            else:    
+                # Searching for time instances
+                where = "(start_time = '%s')" % (start)
+    
+                rows = self.get_registered_maps("id", where, "start_time", dbif)
+    
+                if rows is not None and len(rows) != 0:
+                    if len(rows) > 1:
+                        core.warning(_("More than one map found in a granule. "
+                                       "Temporal granularity seems to be invalid or"
+                                       " the chosen granularity is not a greatest "
+                                       "common divider of all time instances "
+                                       "in the dataset."))
+    
+                    maplist = []
+                    for row in rows:
+                        # Take the first map
+                        map = self.get_new_map_instance(rows[0]["id"])
+    
+                        if self.is_time_absolute():
+                            map.set_absolute_time(start, None)
+                        elif self.is_time_relative():
+                            map.set_relative_time(start, None, 
+                                                  self.get_relative_time_unit())
+    
+                        maplist.append(copy.copy(map))
+    
+                    obj_list.append(copy.copy(maplist))
+                found_gap = True
+            
+            # Gap handling
+            if found_gap:
+                # Found a gap
                 map = self.get_new_map_instance(None)
                 map = self.get_new_map_instance(None)
 
 
                 if self.is_time_absolute():
                 if self.is_time_absolute():
@@ -853,6 +890,57 @@ class AbstractSpaceTimeDataset(AbstractDataset):
 
 
         return rows
         return rows
 
 
+    def rename(self, ident, dbif=None):
+        """!Rename the space time dataset
+
+           This method renames the space time dataset, the map register table
+           and updates the entries in registered maps stds register.
+
+           @param ident: The new identifier name@mapset
+           @param dbif: The database interface to be used
+        """
+
+        dbif, connect = init_dbif(dbif)
+
+        # SELECT all needed information from the database
+        self.select(dbif)
+        
+        # We need to select the registered maps here
+        maps = self.get_registered_maps_as_objects(None, "start_time", dbif)
+        
+        # Safe old identifier
+        old_ident = self.get_id()
+        # We need to rename the old table
+        old_map_register_table = self.get_map_register()
+        
+        # Set new identifier
+        self.set_id(ident)
+        # Create map register table name from new identifier
+        new_map_register_table = self.create_map_register_name()
+        # Set new map register table name
+        self.set_map_register(new_map_register_table)
+        
+        # Get the update statement, we update the table entry of the old identifier
+        statement = self.update(dbif, execute=False, ident=old_ident)
+        
+        # We need to rename the raster register table
+        statement += "ALTER TABLE %s RENAME TO \'%s\';\n"%\
+                     (old_map_register_table, new_map_register_table)
+
+        # We need to rename the space time dataset in the maps register table
+        if maps:
+            for map in maps:
+                map.select()
+                statement += "UPDATE %s SET id = \'%s\' WHERE id = \'%s\';\n"%\
+                             (map.get_stds_register(), ident, old_ident)
+                         
+        
+        # Execute the accumulated statements
+        dbif.execute_transaction(statement)
+        
+        if connect:
+            dbif.close()
+    
     def delete(self, dbif=None, execute=True):
     def delete(self, dbif=None, execute=True):
         """!Delete a space time dataset from the temporal database
         """!Delete a space time dataset from the temporal database
 
 
@@ -926,6 +1014,7 @@ class AbstractSpaceTimeDataset(AbstractDataset):
             In case the map is already registered this function 
             In case the map is already registered this function 
             will break with a warning and return False.
             will break with a warning and return False.
 
 
+           @param map: The AbstractMapDataset object that should be registered
            @param dbif: The database interface to be used
            @param dbif: The database interface to be used
         """
         """
         dbif, connect = init_dbif(dbif)
         dbif, connect = init_dbif(dbif)
@@ -1087,8 +1176,7 @@ class AbstractSpaceTimeDataset(AbstractDataset):
         # We need to create the table and register it
         # We need to create the table and register it
         if stds_register_table is None:
         if stds_register_table is None:
             # Create table name
             # Create table name
-            stds_register_table = stds_name + "_" + \
-                stds_mapset + "_" + map.get_type() + "_register"
+            stds_register_table = self.create_map_register_name()
             # Read the SQL template
             # Read the SQL template
             sql = open(os.path.join(sql_path, 
             sql = open(os.path.join(sql_path, 
                                     "stds_map_register_table_template.sql"), 
                                     "stds_map_register_table_template.sql"), 

+ 33 - 14
lib/python/temporal/base.py

@@ -401,24 +401,33 @@ class SQLDatabaseInterface(DictSQLSerializer):
             dbif.cursor.execute(sql, args)
             dbif.cursor.execute(sql, args)
             dbif.close()
             dbif.close()
 
 
-    def get_update_statement(self):
+    def get_update_statement(self, ident=None):
         """!Return the sql statement and the argument list 
         """!Return the sql statement and the argument list 
-           in database specific style"""
-        return self.serialize("UPDATE", self.get_table_name(), 
+           in database specific style
+           
+           @param ident: The identifier to be updated, useful for renaming
+           
+           """
+        if ident:
+            return self.serialize("UPDATE", self.get_table_name(), 
+                              "WHERE id = \'" + str(ident) + "\'")
+        else:
+            return self.serialize("UPDATE", self.get_table_name(), 
                               "WHERE id = \'" + str(self.ident) + "\'")
                               "WHERE id = \'" + str(self.ident) + "\'")
 
 
-    def get_update_statement_mogrified(self, dbif=None):
+    def get_update_statement_mogrified(self, dbif=None, ident=None):
         """!Return the update statement as mogrified string
         """!Return the update statement as mogrified string
 
 
            @param dbif: The database interface to be used, 
            @param dbif: The database interface to be used, 
                         if None a temporary connection will be established
                         if None a temporary connection will be established
+           @param ident: The identifier to be updated, useful for renaming
         """
         """
         if not dbif:
         if not dbif:
             dbif = SQLDatabaseInterfaceConnection()
             dbif = SQLDatabaseInterfaceConnection()
 
 
-        return dbif.mogrify_sql_statement(self.get_update_statement())
+        return dbif.mogrify_sql_statement(self.get_update_statement(ident))
 
 
-    def update(self, dbif=None):
+    def update(self, dbif=None, ident=None):
         """!Serialize the content of this object and update it in the temporal
         """!Serialize the content of this object and update it in the temporal
            database using the internal identifier
            database using the internal identifier
 
 
@@ -426,11 +435,12 @@ class SQLDatabaseInterface(DictSQLSerializer):
 
 
            @param dbif: The database interface to be used, 
            @param dbif: The database interface to be used, 
                         if None a temporary connection will be established
                         if None a temporary connection will be established
+           @param ident: The identifier to be updated, useful for renaming
         """
         """
         if self.ident is None:
         if self.ident is None:
             raise IOError("Missing identifer")
             raise IOError("Missing identifer")
 
 
-        sql, args = self.get_update_statement()
+        sql, args = self.get_update_statement(indent)
         #print sql
         #print sql
         #print args
         #print args
 
 
@@ -442,34 +452,43 @@ class SQLDatabaseInterface(DictSQLSerializer):
             dbif.cursor.execute(sql, args)
             dbif.cursor.execute(sql, args)
             dbif.close()
             dbif.close()
 
 
-    def get_update_all_statement(self):
+    def get_update_all_statement(self, ident=None):
         """!Return the sql statement and the argument 
         """!Return the sql statement and the argument 
-           list in database specific style"""
-        return self.serialize("UPDATE ALL", self.get_table_name(), 
+           list in database specific style
+           
+           @param ident: The identifier to be updated, useful for renaming
+           """
+        if ident:
+            return self.serialize("UPDATE ALL", self.get_table_name(), 
+                              "WHERE id = \'" + str(ident) + "\'")
+        else:
+            return self.serialize("UPDATE ALL", self.get_table_name(), 
                               "WHERE id = \'" + str(self.ident) + "\'")
                               "WHERE id = \'" + str(self.ident) + "\'")
 
 
-    def get_update_all_statement_mogrified(self, dbif=None):
+    def get_update_all_statement_mogrified(self, dbif=None, ident=None):
         """!Return the update all statement as mogrified string
         """!Return the update all statement as mogrified string
 
 
            @param dbif: The database interface to be used, 
            @param dbif: The database interface to be used, 
                         if None a temporary connection will be established
                         if None a temporary connection will be established
+           @param ident: The identifier to be updated, useful for renaming
         """
         """
         if not dbif:
         if not dbif:
             dbif = SQLDatabaseInterfaceConnection()
             dbif = SQLDatabaseInterfaceConnection()
 
 
-        return dbif.mogrify_sql_statement(self.get_update_all_statement())
+        return dbif.mogrify_sql_statement(self.get_update_all_statement(ident))
 
 
-    def update_all(self, dbif=None):
+    def update_all(self, dbif=None, ident=None):
         """!Serialize the content of this object, including None objects, 
         """!Serialize the content of this object, including None objects, 
         and update it in the temporal database using the internal identifier
         and update it in the temporal database using the internal identifier
 
 
            @param dbif: The database interface to be used, 
            @param dbif: The database interface to be used, 
                         if None a temporary connection will be established
                         if None a temporary connection will be established
+           @param ident: The identifier to be updated, useful for renaming
         """
         """
         if self.ident is None:
         if self.ident is None:
             raise IOError("Missing identifer")
             raise IOError("Missing identifer")
 
 
-        sql, args = self.get_update_all_statement()
+        sql, args = self.get_update_all_statement(ident)
         #print sql
         #print sql
         #print args
         #print args
 
 

+ 7 - 4
lib/python/temporal/space_time_datasets_tools.py

@@ -230,13 +230,17 @@ def register_maps_in_space_time_dataset(
                                    "Unable to update %s map <%s>. "
                                    "Unable to update %s map <%s>. "
                                    "Overwrite flag is not set.") %
                                    "Overwrite flag is not set.") %
                                (map.get_type(), map.get_map_id()))
                                (map.get_type(), map.get_map_id()))
+                
+                # Simple registration is allowed
+                if name:
+                    map_object_list.append(map)
                 # Jump to next map
                 # Jump to next map
                 continue
                 continue
             
             
             # Select information from temporal database
             # Select information from temporal database
             map.select(dbif)
             map.select(dbif)
             
             
-            # Safe the datasets that must be updated
+            # Save the datasets that must be updated
             datasets = map.get_registered_datasets(dbif)
             datasets = map.get_registered_datasets(dbif)
             if datasets:
             if datasets:
                 for dataset in datasets:
                 for dataset in datasets:
@@ -293,7 +297,7 @@ def register_maps_in_space_time_dataset(
         dbif.execute_transaction(statement)
         dbif.execute_transaction(statement)
 
 
     # Finally Register the maps in the space time dataset
     # Finally Register the maps in the space time dataset
-    if name:
+    if name and map_object_list:
         statement = ""
         statement = ""
         count = 0
         count = 0
         num_maps = len(map_object_list)
         num_maps = len(map_object_list)
@@ -304,7 +308,7 @@ def register_maps_in_space_time_dataset(
             count += 1
             count += 1
 
 
     # Update the space time tables
     # Update the space time tables
-    if name:
+    if name and map_object_list:
         core.message(_("Update space time raster dataset"))
         core.message(_("Update space time raster dataset"))
         sp.update_from_registered_maps(dbif)
         sp.update_from_registered_maps(dbif)
         
         
@@ -353,7 +357,6 @@ def assign_valid_time_to_map(ttype, map, start, end, unit, increment=None, mult=
     if ttype == "absolute":
     if ttype == "absolute":
         start_time = string_to_datetime(start)
         start_time = string_to_datetime(start)
         if start_time is None:
         if start_time is None:
-            dbif.close()
             core.fatal(_("Unable to convert string \"%s\"into a "
             core.fatal(_("Unable to convert string \"%s\"into a "
                          "datetime object") % (start))
                          "datetime object") % (start))
         end_time = None
         end_time = None