v.db.reconnect.all.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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. #% keywords: vector
  19. #% keywords: attribute table
  20. #% keywords: 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. # substitute variables (gisdbase, location_name, mapset)
  55. def substitute_db(database):
  56. gisenv = grass.gisenv()
  57. tmpl = string.Template(database)
  58. return tmpl.substitute(GISDBASE = gisenv['GISDBASE'],
  59. LOCATION_NAME = gisenv['LOCATION_NAME'],
  60. MAPSET = gisenv['MAPSET'])
  61. # create database if doesn't exist
  62. def create_db(driver, database):
  63. subst_database = substitute_db(database)
  64. if driver == 'dbf':
  65. path = subst_database
  66. # check if destination directory exists
  67. if not os.path.isdir(path):
  68. # create dbf database
  69. os.makedirs(path)
  70. return True
  71. return False
  72. if driver == 'sqlite':
  73. path = os.path.dirname(subst_database)
  74. # check if destination directory exists
  75. if not os.path.isdir(path):
  76. os.makedirs(path)
  77. if subst_database in grass.read_command('db.databases', quiet = True,
  78. driver = driver).splitlines():
  79. return False
  80. grass.info(_("Target database doesn't exist, "
  81. "creating a new database using <%s> driver...") % driver)
  82. if 0 != grass.run_command('db.createdb', driver = driver,
  83. database = subst_database):
  84. grass.fatal(_("Unable to create database <%s> by driver <%s>") % \
  85. (subst_database, driver))
  86. return False
  87. # copy tables if required (-c)
  88. def copy_tab(from_driver, from_database, from_table,
  89. to_driver, to_database, to_table):
  90. if to_table in grass.read_command('db.tables', quiet = True,
  91. driver = to_driver,
  92. database = to_database,
  93. stderr = nuldev).splitlines():
  94. return False
  95. grass.info("Copying table <%s> to target database..." % to_table)
  96. if 0 != grass.run_command('db.copy', from_driver = from_driver,
  97. from_database = from_database,
  98. from_table = from_table, to_driver = to_driver,
  99. to_database = to_database,
  100. to_table = to_table):
  101. grass.fatal(_("Unable to copy table <%s>") % from_table)
  102. return True
  103. # drop tables if required (-d)
  104. def drop_tab(vector, layer, table, driver, database):
  105. # disconnect
  106. if 0 != grass.run_command('v.db.connect', flags = 'd', quiet = True, map = vector,
  107. layer = layer, table = table):
  108. grass.warning(_("Unable to disconnect table <%s> from vector <%s>") % (table, vector))
  109. # drop table
  110. if 0 != grass.run_command('db.droptable', quiet = True, flags = 'f',
  111. driver = driver, database = database,
  112. table = table):
  113. grass.fatal(_("Unable to drop table <%s>") % table)
  114. # create index on key column
  115. def create_index(driver, database, table, index_name, key):
  116. if driver == 'dbf':
  117. return False
  118. grass.info(_("Creating index <%s>...") % index_name)
  119. if 0 != grass.run_command('db.execute', quiet = True,
  120. driver = driver, database = database,
  121. sql = "create unique index %s on %s(%s)" % (index_name, table, key)):
  122. grass.warning(_("Unable to create index <%s>") % index_name)
  123. def main():
  124. # old connection
  125. old_database = options['old_database']
  126. old_schema = options['old_schema']
  127. # new connection
  128. default_connection = grass.db_connection()
  129. if options['new_driver']:
  130. new_driver = options['new_driver']
  131. else:
  132. new_driver = default_connection['driver']
  133. if options['new_database']:
  134. new_database = options['new_database']
  135. else:
  136. new_database = default_connection['database']
  137. if options['new_schema']:
  138. new_schema = options['new_schema']
  139. else:
  140. new_schema = default_connection['schema']
  141. if old_database == '':
  142. old_database = None
  143. old_database_subst = None
  144. if old_database is not None:
  145. old_database_subst = substitute_db(old_database)
  146. new_database_subst = substitute_db(new_database)
  147. if old_database_subst == new_database_subst and old_schema == new_schema:
  148. grass.fatal(_("Old and new database connection is identical. Nothing to do."))
  149. mapset = grass.gisenv()['MAPSET']
  150. vectors = grass.list_grouped('vect')[mapset]
  151. num_vectors = len(vectors)
  152. if flags['c']:
  153. # create new database if not existing
  154. create_db(new_driver, new_database)
  155. i = 0
  156. for vect in vectors:
  157. vect = "%s@%s" % (vect, mapset)
  158. i += 1
  159. grass.message(_("%s\nReconnecting vector map <%s> (%d of %d)...\n%s") % \
  160. ('-' * 80, vect, i, num_vectors, '-' * 80))
  161. for f in grass.vector_db(vect, stderr = nuldev).itervalues():
  162. layer = f['layer']
  163. schema_table = f['table']
  164. key = f['key']
  165. database = f['database']
  166. driver = f['driver']
  167. # split schema.table
  168. if '.' in schema_table:
  169. schema, table = schema_table.split('.', 1)
  170. else:
  171. schema = ''
  172. table = schema_table
  173. if new_schema:
  174. new_schema_table = "%s.%s" % (new_schema, table)
  175. else:
  176. new_schema_table = table
  177. grass.debug("DATABASE = '%s' SCHEMA = '%s' TABLE = '%s' ->\n"
  178. " NEW_DATABASE = '%s' NEW_SCHEMA_TABLE = '%s'" % \
  179. (old_database, schema, table, new_database, new_schema_table))
  180. do_reconnect = True
  181. if old_database_subst is not None:
  182. if database != old_database_subst:
  183. do_reconnect = False
  184. if database == new_database_subst:
  185. do_reconnect = False
  186. if schema != old_schema:
  187. do_reconnect = False
  188. if do_reconnect == True:
  189. grass.verbose(_("Reconnecting layer %d...") % layer)
  190. if flags['c']:
  191. # check if table exists in new database
  192. copy_tab(driver, database, schema_table,
  193. new_driver, new_database, new_schema_table)
  194. # drop original table if required
  195. if flags['d']:
  196. drop_tab(vect, layer, schema_table, driver, substitute_db(database))
  197. # reconnect tables (don't use substituted new_database)
  198. # NOTE: v.db.connect creates an index on the key column
  199. if 0 != grass.run_command('v.db.connect', flags = 'o', quiet = True, map = vect,
  200. layer = layer, driver = new_driver, database = new_database,
  201. table = new_schema_table, key = key):
  202. grass.warning(_("Unable to connect table <%s> to vector <%s> on layer <%s>") %
  203. (table, vect, str(layer)))
  204. else:
  205. if database != new_database_subst:
  206. grass.warning(_("Layer <%d> will not be reconnected because "
  207. "database or schema do not match.") % layer)
  208. return 0
  209. if __name__ == "__main__":
  210. options, flags = grass.parser()
  211. nuldev = file(os.devnull, 'w')
  212. sys.exit(main())