فهرست منبع

WIP upgrade tgis db (#306)

* upgrade tgis db WIP

* create/drop all views when upgrading tgis db

* improve backup howto message, mention t.upgrade

* fix create_temporal_database_views issues

* wording

Co-Authored-By: Veronica Andreo <veroandreo@gmail.com>

* wording

Co-Authored-By: Veronica Andreo <veroandreo@gmail.com>

* fix typo

Co-Authored-By: Veronica Andreo <veroandreo@gmail.com>

* simplify error messaging

* message formatting

* minimal change in the message

Co-authored-by: Veronica Andreo <veroandreo@gmail.com>
Martin Landa 5 سال پیش
والد
کامیت
61b8d40fd2
3فایلهای تغییر یافته به همراه159 افزوده شده و 37 حذف شده
  1. 112 37
      lib/python/temporal/core.py
  2. 29 0
      lib/temporal/SQL/drop_views.sql
  3. 18 0
      lib/temporal/SQL/upgrade_db_2_to_3.sql

+ 112 - 37
lib/python/temporal/core.py

@@ -475,7 +475,7 @@ def get_available_temporal_mapsets():
 ###############################################################################
 ###############################################################################
 
 
 
 
-def init(raise_fatal_error=False):
+def init(raise_fatal_error=False, skip_db_version_check=False):
     """This function set the correct database backend from GRASS environmental
     """This function set the correct database backend from GRASS environmental
        variables and creates the grass temporal database structure for raster,
        variables and creates the grass temporal database structure for raster,
        vector and raster3d maps as well as for the space-time datasets strds,
        vector and raster3d maps as well as for the space-time datasets strds,
@@ -516,6 +516,10 @@ def init(raise_fatal_error=False):
                                   exception will be raised in case a fatal
                                   exception will be raised in case a fatal
                                   error occurs in the init process, otherwise
                                   error occurs in the init process, otherwise
                                   sys.exit(1) will be called.
                                   sys.exit(1) will be called.
+        :param skip_db_version_check: Set this True to skip mismatch temporal
+                                      database version check.
+                                      Recommended to be used only for
+                                      upgrade_temporal_database().
     """
     """
     # We need to set the correct database backend and several global variables
     # We need to set the correct database backend and several global variables
     # from the GRASS mapset specific environment variables of g.gisenv and t.connect
     # from the GRASS mapset specific environment variables of g.gisenv and t.connect
@@ -523,6 +527,7 @@ def init(raise_fatal_error=False):
     global tgis_database
     global tgis_database
     global tgis_database_string
     global tgis_database_string
     global tgis_dbmi_paramstyle
     global tgis_dbmi_paramstyle
+    global tgis_db_version
     global raise_on_error
     global raise_on_error
     global enable_mapset_check
     global enable_mapset_check
     global enable_timestamp_write
     global enable_timestamp_write
@@ -646,25 +651,34 @@ def init(raise_fatal_error=False):
         if dbif.fetchone()[0]:
         if dbif.fetchone()[0]:
             db_exists = True
             db_exists = True
 
 
-    backup_howto = "The format of your actual temporal database is not " \
-                   "supported any more.\nSolution: You need to export it by " \
-                   "restoring the GRASS GIS version used for creating this DB"\
-                   ". From there, create a backup of your temporal database "\
-                   "to avoid the loss of your temporal data.\nNotes: Use " \
-                   "t.rast.export and t.vect.export to make a backup of your" \
-                   " existing space time datasets.To safe the timestamps of" \
-                   " your existing maps and space time datasets, use " \
-                   "t.rast.list, t.vect.list and t.rast3d.list. "\
-                   "You can register the existing time stamped maps easily if"\
-                   " you export columns=id,start_time,end_time into text "\
-                   "files and use t.register to register them again in new" \
-                   " created space time datasets (t.create). After the backup"\
-                   " remove the existing temporal database, a new one will be"\
-                   " created automatically.\n"
+    backup_howto = _("The format of your actual temporal database is not " \
+                     "supported any more.\n" \
+                     "Please create a backup of your temporal database "\
+                     "to avoid lossing data.\nSOLUTION: ")
+    if tgis_db_version > 2:
+        backup_howto += _("Run t.upgrade command installed from " \
+                          "GRASS Addons in order to upgrade your temporal database.\n")
+    else:
+        backup_howto += _("You need to export it by " \
+                          "restoring the GRASS GIS version used for creating this DB."\
+                          "Notes: Use t.rast.export and t.vect.export "\
+                          "to make a backup of your" \
+                          " existing space time datasets. To save the timestamps of" \
+                          " your existing maps and space time datasets, use " \
+                          "t.rast.list, t.vect.list and t.rast3d.list. "\
+                          "You can register the existing time stamped maps easily if"\
+                          " you export columns=id,start_time,end_time into text "\
+                          "files and use t.register to register them again in new" \
+                          " created space time datasets (t.create). After the backup"\
+                          " remove the existing temporal database, a new one will be"\
+                          " created automatically.\n")
 
 
     if db_exists is True:
     if db_exists is True:
-        # Check the version of the temporal database
         dbif.close()
         dbif.close()
+        if  skip_db_version_check is True:
+            return
+
+        # Check the version of the temporal database
         dbif.connect()
         dbif.connect()
         metadata = get_tgis_metadata(dbif)
         metadata = get_tgis_metadata(dbif)
         dbif.close()
         dbif.close()
@@ -704,6 +718,25 @@ def get_database_info_string():
 
 
 ###############################################################################
 ###############################################################################
 
 
+def _create_temporal_database_views(dbif):
+    """Create all views in the temporal database (internal use only)
+
+    Used by create_temporal_database() and upgrade_temporal_database().
+
+    :param dbif: The database interface to be used
+    """
+    template_path = get_sql_template_path()
+
+    for sql_filename in ("raster_views",
+                         "raster3d_views",
+                         "vector_views",
+                         "strds_views",
+                         "str3ds_views",
+                         "stvds_views"):
+        sql_filepath = open(os.path.join(template_path,
+                                         sql_filename + '.sql'),
+                            'r').read()
+        dbif.execute_transaction(sql_filepath)
 
 
 def create_temporal_database(dbif):
 def create_temporal_database(dbif):
     """This function will create the temporal database
     """This function will create the temporal database
@@ -732,13 +765,6 @@ def create_temporal_database(dbif):
     vector_metadata_sql = open(os.path.join(template_path,
     vector_metadata_sql = open(os.path.join(template_path,
                                             "vector_metadata_table.sql"),
                                             "vector_metadata_table.sql"),
                                'r').read()
                                'r').read()
-    raster_views_sql = open(os.path.join(template_path, "raster_views.sql"),
-                            'r').read()
-    raster3d_views_sql = open(os.path.join(template_path,
-                                           "raster3d_views.sql"), 'r').read()
-    vector_views_sql = open(os.path.join(template_path, "vector_views.sql"),
-                            'r').read()
-
     stds_tables_template_sql = open(os.path.join(template_path,
     stds_tables_template_sql = open(os.path.join(template_path,
                                                  "stds_tables_template.sql"),
                                                  "stds_tables_template.sql"),
                                     'r').read()
                                     'r').read()
@@ -751,12 +777,6 @@ def create_temporal_database(dbif):
     stvds_metadata_sql = open(os.path.join(template_path,
     stvds_metadata_sql = open(os.path.join(template_path,
                                            "stvds_metadata_table.sql"),
                                            "stvds_metadata_table.sql"),
                               'r').read()
                               'r').read()
-    strds_views_sql = open(os.path.join(template_path, "strds_views.sql"),
-                           'r').read()
-    str3ds_views_sql = open(os.path.join(template_path, "str3ds_views.sql"),
-                            'r').read()
-    stvds_views_sql = open(os.path.join(template_path, "stvds_views.sql"),
-                           'r').read()
 
 
     # Create the raster, raster3d and vector tables SQL statements
     # Create the raster, raster3d and vector tables SQL statements
     raster_tables_sql = map_tables_template_sql.replace("GRASS_MAP", "raster")
     raster_tables_sql = map_tables_template_sql.replace("GRASS_MAP", "raster")
@@ -803,27 +823,24 @@ def create_temporal_database(dbif):
     if dbif.connected is not True:
     if dbif.connected is not True:
         dbif.connect()
         dbif.connect()
 
 
-    # Execute the SQL statements for sqlite
+    # Execute the SQL statements
     # Create the global tables for the native grass datatypes
     # Create the global tables for the native grass datatypes
     dbif.execute_transaction(raster_tables_sql)
     dbif.execute_transaction(raster_tables_sql)
     dbif.execute_transaction(raster_metadata_sql)
     dbif.execute_transaction(raster_metadata_sql)
-    dbif.execute_transaction(raster_views_sql)
     dbif.execute_transaction(vector_tables_sql)
     dbif.execute_transaction(vector_tables_sql)
     dbif.execute_transaction(vector_metadata_sql)
     dbif.execute_transaction(vector_metadata_sql)
-    dbif.execute_transaction(vector_views_sql)
     dbif.execute_transaction(raster3d_tables_sql)
     dbif.execute_transaction(raster3d_tables_sql)
     dbif.execute_transaction(raster3d_metadata_sql)
     dbif.execute_transaction(raster3d_metadata_sql)
-    dbif.execute_transaction(raster3d_views_sql)
     # Create the tables for the new space-time datatypes
     # Create the tables for the new space-time datatypes
     dbif.execute_transaction(strds_tables_sql)
     dbif.execute_transaction(strds_tables_sql)
     dbif.execute_transaction(strds_metadata_sql)
     dbif.execute_transaction(strds_metadata_sql)
-    dbif.execute_transaction(strds_views_sql)
     dbif.execute_transaction(stvds_tables_sql)
     dbif.execute_transaction(stvds_tables_sql)
     dbif.execute_transaction(stvds_metadata_sql)
     dbif.execute_transaction(stvds_metadata_sql)
-    dbif.execute_transaction(stvds_views_sql)
     dbif.execute_transaction(str3ds_tables_sql)
     dbif.execute_transaction(str3ds_tables_sql)
     dbif.execute_transaction(str3ds_metadata_sql)
     dbif.execute_transaction(str3ds_metadata_sql)
-    dbif.execute_transaction(str3ds_views_sql)
+
+    # Create views
+    self._create_temporal_database_views(dbif)
 
 
     # The delete trigger
     # The delete trigger
     dbif.execute_transaction(delete_trigger_sql)
     dbif.execute_transaction(delete_trigger_sql)
@@ -844,6 +861,64 @@ def create_temporal_database(dbif):
 ###############################################################################
 ###############################################################################
 
 
 
 
+def upgrade_temporal_database(dbif):
+    """This function will upgrade the temporal database if needed.
+
+       It will update all tables and triggers that are requested by
+       currently supported TGIS DB version.
+
+       :param dbif: The database interface to be used
+    """
+    global tgis_database_string
+    global tgis_db_version
+
+    metadata = get_tgis_metadata(dbif)
+
+    msgr = get_tgis_message_interface()
+    if metadata is None:
+        msgr.fatal(_("Unable to receive temporal database metadata.\n"
+                     "Current temporal database info:%(info)s") % (
+                         {"info": get_database_info_string()}))
+    upgrade_db_from = None
+    for entry in metadata:
+        if "tgis_db_version" in entry and entry[1] != str(tgis_db_version):
+            upgrade_db_from = entry[1]
+            break
+
+    if upgrade_db_from is None:
+        msgr.message(_("Temporal database is up-to-date. Operation canceled"))
+        dbif.close()
+        return
+
+    template_path = get_sql_template_path()
+    try:
+        upgrade_db_sql = open(os.path.join(
+            template_path,
+            "upgrade_db_%s_to_%s.sql" % (upgrade_db_from, tgis_db_version)),
+            'r').read()
+    except FileNotFoundError:
+        msgr.fatal(_("Unsupported TGIS DB upgrade scenario: from version %s to %s") % \
+                   (upgrade_db_from, tgis_db_version))
+
+    drop_views_sql = open(
+        os.path.join(template_path, "drop_views.sql"),
+        'r').read()
+
+    msgr.message(
+        _("Upgrading temporal database <%s> from version %s to %s...") % \
+        (tgis_database_string, upgrade_db_from, tgis_db_version))
+    # Drop views
+    dbif.execute_transaction(drop_views_sql)
+    # Perform upgrade
+    dbif.execute_transaction(upgrade_db_sql)
+    # Recreate views
+    _create_temporal_database_views(dbif)
+
+    dbif.close()
+
+###############################################################################
+
+
 def _create_tgis_metadata_table(content, dbif=None):
 def _create_tgis_metadata_table(content, dbif=None):
     """!Create the temporal gis metadata table which stores all metadata
     """!Create the temporal gis metadata table which stores all metadata
        information about the temporal database.
        information about the temporal database.

+ 29 - 0
lib/temporal/SQL/drop_views.sql

@@ -0,0 +1,29 @@
+--#############################################################################
+-- This SQL script drops all existing vies (used by upgrade_temporal_database())
+--
+-- Author: Martin Landa landa.martin <at> gmail <dot> com
+--#############################################################################
+
+-- raster_views
+DROP VIEW raster_view_abs_time;
+DROP VIEW raster_view_rel_time;
+
+-- raster3d_views
+DROP VIEW raster3d_view_abs_time;
+DROP VIEW raster3d_view_rel_time;
+
+-- vector_views
+DROP VIEW vector_view_abs_time;
+DROP VIEW vector_view_rel_time;
+
+-- strds_views
+DROP VIEW strds_view_abs_time;
+DROP VIEW strds_view_rel_time;
+
+-- str3ds_views
+DROP VIEW str3ds_view_abs_time;
+DROP VIEW str3ds_view_rel_time;
+
+-- stvds_views
+DROP VIEW stvds_view_abs_time;
+DROP VIEW stvds_view_rel_time;

+ 18 - 0
lib/temporal/SQL/upgrade_db_2_to_3.sql

@@ -0,0 +1,18 @@
+--#############################################################################
+-- This SQL script upgrades TGIS DB from version 2 to version 3.
+--
+-- Author: Martin Landa landa.martin <at> gmail <dot> com
+--#############################################################################
+
+-- raster_metadata_table.sql
+ALTER TABLE raster_metadata
+ ADD COLUMN band_reference VARCHAR;
+
+-- strds_metadata_table.sql
+ALTER TABLE strds_metadata
+ ADD COLUMN number_of_bands INTEGER;
+
+-- tgis_metadata
+UPDATE tgis_metadata
+  SET value = '3'
+  WHERE key = 'tgis_db_version';