v.db.reconnect.all.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #!/usr/bin/env python
  2. ############################################################################
  3. #
  4. # MODULE: v.db.reconnect.all
  5. # AUTHOR(S): Radim Blazek
  6. # Converted to Python by Glynn Clements
  7. # Update for GRASS 7 by Markus Metz
  8. # PURPOSE: Reconnect all vector maps from the current mapset
  9. # COPYRIGHT: (C) 2004, 2012 by the GRASS Development Team
  10. #
  11. # This program is free software under the GNU General
  12. # Public License (>=v2). Read the file COPYING that
  13. # comes with GRASS for details.
  14. #
  15. #############################################################################
  16. #%module
  17. #% description: Reconnects attribute tables for all vector maps from the current mapset to a new database.
  18. #% keyword: vector
  19. #% keyword: attribute table
  20. #% keyword: database
  21. #%end
  22. #%flag
  23. #% key: c
  24. #% description: Copy attribute tables to the target database if not exist
  25. #%end
  26. #%flag
  27. #% key: d
  28. #% description: Delete attribute tables from the source database
  29. #%end
  30. #%option G_OPT_DB_DATABASE
  31. #% key: old_database
  32. #% description: Name of source database
  33. #%end
  34. #%option G_OPT_DB_SCHEMA
  35. #% key: old_schema
  36. #% label: Name of source database schema
  37. #%end
  38. #%option
  39. #% key: new_driver
  40. #% description: Name for target driver
  41. #%end
  42. #%option G_OPT_DB_DATABASE
  43. #% key: new_database
  44. #% description: Name for target database
  45. #%end
  46. #%option G_OPT_DB_SCHEMA
  47. #% key: new_schema
  48. #% label: Name for target database schema
  49. #%end
  50. import sys
  51. import os
  52. import string
  53. import grass.script as grass
  54. from grass.exceptions import CalledModuleError
  55. # substitute variables (gisdbase, location_name, mapset)
  56. def substitute_db(database):
  57. gisenv = grass.gisenv()
  58. tmpl = string.Template(database)
  59. return tmpl.substitute(GISDBASE = gisenv['GISDBASE'],
  60. LOCATION_NAME = gisenv['LOCATION_NAME'],
  61. MAPSET = gisenv['MAPSET'])
  62. # create database if doesn't exist
  63. def create_db(driver, database):
  64. subst_database = substitute_db(database)
  65. if driver == 'dbf':
  66. path = subst_database
  67. # check if destination directory exists
  68. if not os.path.isdir(path):
  69. # create dbf database
  70. os.makedirs(path)
  71. return True
  72. return False
  73. if driver == 'sqlite':
  74. path = os.path.dirname(subst_database)
  75. # check if destination directory exists
  76. if not os.path.isdir(path):
  77. os.makedirs(path)
  78. if subst_database in grass.read_command('db.databases', quiet = True,
  79. driver = driver).splitlines():
  80. return False
  81. grass.info(_("Target database doesn't exist, "
  82. "creating a new database using <%s> driver...") % driver)
  83. try:
  84. grass.run_command('db.createdb', driver = driver,
  85. database = subst_database)
  86. except CalledModuleError:
  87. grass.fatal(_("Unable to create database <%s> by driver <%s>") % \
  88. (subst_database, driver))
  89. return False
  90. # copy tables if required (-c)
  91. def copy_tab(from_driver, from_database, from_table,
  92. to_driver, to_database, to_table):
  93. if to_table in grass.read_command('db.tables', quiet = True,
  94. driver = to_driver,
  95. database = to_database,
  96. stderr = nuldev).splitlines():
  97. return False
  98. grass.info("Copying table <%s> to target database..." % to_table)
  99. try:
  100. grass.run_command('db.copy', from_driver = from_driver,
  101. from_database = from_database,
  102. from_table = from_table, to_driver = to_driver,
  103. to_database = to_database,
  104. to_table = to_table)
  105. except CalledModuleError:
  106. grass.fatal(_("Unable to copy table <%s>") % from_table)
  107. return True
  108. # drop tables if required (-d)
  109. def drop_tab(vector, layer, table, driver, database):
  110. # disconnect
  111. try:
  112. grass.run_command('v.db.connect', flags = 'd', quiet = True, map = vector,
  113. layer = layer, table = table)
  114. except CalledModuleError:
  115. grass.warning(_("Unable to disconnect table <%s> from vector <%s>") % (table, vector))
  116. # drop table
  117. try:
  118. grass.run_command('db.droptable', quiet = True, flags = 'f',
  119. driver = driver, database = database,
  120. table = table)
  121. except CalledModuleError:
  122. grass.fatal(_("Unable to drop table <%s>") % table)
  123. # create index on key column
  124. def create_index(driver, database, table, index_name, key):
  125. if driver == 'dbf':
  126. return False
  127. grass.info(_("Creating index <%s>...") % index_name)
  128. try:
  129. grass.run_command('db.execute', quiet = True,
  130. driver = driver, database = database,
  131. sql = "create unique index %s on %s(%s)" % (index_name, table, key))
  132. except CalledModuleError:
  133. grass.warning(_("Unable to create index <%s>") % index_name)
  134. def main():
  135. # old connection
  136. old_database = options['old_database']
  137. old_schema = options['old_schema']
  138. # new connection
  139. default_connection = grass.db_connection()
  140. if options['new_driver']:
  141. new_driver = options['new_driver']
  142. else:
  143. new_driver = default_connection['driver']
  144. if options['new_database']:
  145. new_database = options['new_database']
  146. else:
  147. new_database = default_connection['database']
  148. if options['new_schema']:
  149. new_schema = options['new_schema']
  150. else:
  151. new_schema = default_connection['schema']
  152. if old_database == '':
  153. old_database = None
  154. old_database_subst = None
  155. if old_database is not None:
  156. old_database_subst = substitute_db(old_database)
  157. new_database_subst = substitute_db(new_database)
  158. if old_database_subst == new_database_subst and old_schema == new_schema:
  159. grass.fatal(_("Old and new database connection is identical. Nothing to do."))
  160. mapset = grass.gisenv()['MAPSET']
  161. vectors = grass.list_grouped('vect')[mapset]
  162. num_vectors = len(vectors)
  163. if flags['c']:
  164. # create new database if not existing
  165. create_db(new_driver, new_database)
  166. i = 0
  167. for vect in vectors:
  168. vect = "%s@%s" % (vect, mapset)
  169. i += 1
  170. grass.message(_("%s\nReconnecting vector map <%s> (%d of %d)...\n%s") % \
  171. ('-' * 80, vect, i, num_vectors, '-' * 80))
  172. for f in grass.vector_db(vect, stderr = nuldev).itervalues():
  173. layer = f['layer']
  174. schema_table = f['table']
  175. key = f['key']
  176. database = f['database']
  177. driver = f['driver']
  178. # split schema.table
  179. if '.' in schema_table:
  180. schema, table = schema_table.split('.', 1)
  181. else:
  182. schema = ''
  183. table = schema_table
  184. if new_schema:
  185. new_schema_table = "%s.%s" % (new_schema, table)
  186. else:
  187. new_schema_table = table
  188. grass.debug("DATABASE = '%s' SCHEMA = '%s' TABLE = '%s' ->\n"
  189. " NEW_DATABASE = '%s' NEW_SCHEMA_TABLE = '%s'" % \
  190. (old_database, schema, table, new_database, new_schema_table))
  191. do_reconnect = True
  192. if old_database_subst is not None:
  193. if database != old_database_subst:
  194. do_reconnect = False
  195. if database == new_database_subst:
  196. do_reconnect = False
  197. if schema != old_schema:
  198. do_reconnect = False
  199. if do_reconnect == True:
  200. grass.verbose(_("Reconnecting layer %d...") % layer)
  201. if flags['c']:
  202. # check if table exists in new database
  203. copy_tab(driver, database, schema_table,
  204. new_driver, new_database, new_schema_table)
  205. # drop original table if required
  206. if flags['d']:
  207. drop_tab(vect, layer, schema_table, driver, substitute_db(database))
  208. # reconnect tables (don't use substituted new_database)
  209. # NOTE: v.db.connect creates an index on the key column
  210. try:
  211. grass.run_command('v.db.connect', flags = 'o', quiet = True, map = vect,
  212. layer = layer, driver = new_driver, database = new_database,
  213. table = new_schema_table, key = key)
  214. except CalledModuleError:
  215. grass.warning(_("Unable to connect table <%s> to vector <%s> on layer <%s>") %
  216. (table, vect, str(layer)))
  217. else:
  218. if database != new_database_subst:
  219. grass.warning(_("Layer <%d> will not be reconnected because "
  220. "database or schema do not match.") % layer)
  221. return 0
  222. if __name__ == "__main__":
  223. options, flags = grass.parser()
  224. nuldev = file(os.devnull, 'w')
  225. sys.exit(main())