v.db.reconnect.all.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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 gscript
  54. from grass.exceptions import CalledModuleError
  55. # substitute variables (gisdbase, location_name, mapset)
  56. def substitute_db(database):
  57. gisenv = gscript.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 gscript.read_command('db.databases', quiet=True,
  79. driver=driver).splitlines():
  80. return False
  81. gscript.info(_("Target database doesn't exist, "
  82. "creating a new database using <%s> driver...") % driver)
  83. try:
  84. gscript.run_command('db.createdb', driver=driver,
  85. database=subst_database)
  86. except CalledModuleError:
  87. gscript.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 gscript.read_command('db.tables', quiet=True,
  94. driver=to_driver,
  95. database=to_database,
  96. stderr=nuldev).splitlines():
  97. return False
  98. gscript.info("Copying table <%s> to target database..." % to_table)
  99. try:
  100. gscript.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. gscript.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. gscript.run_command('v.db.connect', flags='d', quiet=True, map=vector,
  113. layer=layer, table=table)
  114. except CalledModuleError:
  115. gscript.warning(_("Unable to disconnect table <%s> from vector <%s>") %
  116. (table, vector))
  117. # drop table
  118. try:
  119. gscript.run_command('db.droptable', quiet=True, flags='f',
  120. driver=driver, database=database,
  121. table=table)
  122. except CalledModuleError:
  123. gscript.fatal(_("Unable to drop table <%s>") % table)
  124. # create index on key column
  125. def create_index(driver, database, table, index_name, key):
  126. if driver == 'dbf':
  127. return False
  128. gscript.info(_("Creating index <%s>...") % index_name)
  129. try:
  130. gscript.run_command('db.execute', quiet=True, driver=driver,
  131. database=database,
  132. sql="create unique index %s on %s(%s)" %
  133. (index_name, table, key))
  134. except CalledModuleError:
  135. gscript.warning(_("Unable to create index <%s>") % index_name)
  136. def main():
  137. # old connection
  138. old_database = options['old_database']
  139. old_schema = options['old_schema']
  140. # new connection
  141. default_connection = gscript.db_connection()
  142. if options['new_driver']:
  143. new_driver = options['new_driver']
  144. else:
  145. new_driver = default_connection['driver']
  146. if options['new_database']:
  147. new_database = options['new_database']
  148. else:
  149. new_database = default_connection['database']
  150. if options['new_schema']:
  151. new_schema = options['new_schema']
  152. else:
  153. new_schema = default_connection['schema']
  154. if old_database == '':
  155. old_database = None
  156. old_database_subst = None
  157. if old_database is not None:
  158. old_database_subst = substitute_db(old_database)
  159. new_database_subst = substitute_db(new_database)
  160. if old_database_subst == new_database_subst and old_schema == new_schema:
  161. gscript.fatal(_("Old and new database connection is identical. "
  162. "Nothing to do."))
  163. mapset = gscript.gisenv()['MAPSET']
  164. vectors = gscript.list_grouped('vect')[mapset]
  165. num_vectors = len(vectors)
  166. if flags['c']:
  167. # create new database if not existing
  168. create_db(new_driver, new_database)
  169. i = 0
  170. for vect in vectors:
  171. vect = "%s@%s" % (vect, mapset)
  172. i += 1
  173. gscript.message(_("%s\nReconnecting vector map <%s> "
  174. "(%d of %d)...\n%s") %
  175. ('-' * 80, vect, i, num_vectors, '-' * 80))
  176. for f in gscript.vector_db(vect, stderr=nuldev).values():
  177. layer = f['layer']
  178. schema_table = f['table']
  179. key = f['key']
  180. database = f['database']
  181. driver = f['driver']
  182. # split schema.table
  183. if '.' in schema_table:
  184. schema, table = schema_table.split('.', 1)
  185. else:
  186. schema = ''
  187. table = schema_table
  188. if new_schema:
  189. new_schema_table = "%s.%s" % (new_schema, table)
  190. else:
  191. new_schema_table = table
  192. gscript.debug("DATABASE = '%s' SCHEMA = '%s' TABLE = '%s' ->\n"
  193. " NEW_DATABASE = '%s' NEW_SCHEMA_TABLE = '%s'" %
  194. (old_database, schema, table, new_database,
  195. new_schema_table))
  196. do_reconnect = True
  197. if old_database_subst is not None:
  198. if database != old_database_subst:
  199. do_reconnect = False
  200. if database == new_database_subst:
  201. do_reconnect = False
  202. if schema != old_schema:
  203. do_reconnect = False
  204. if do_reconnect == True:
  205. gscript.verbose(_("Reconnecting layer %d...") % layer)
  206. if flags['c']:
  207. # check if table exists in new database
  208. copy_tab(driver, database, schema_table,
  209. new_driver, new_database, new_schema_table)
  210. # drop original table if required
  211. if flags['d']:
  212. drop_tab(
  213. vect,
  214. layer,
  215. schema_table,
  216. driver,
  217. substitute_db(database))
  218. # reconnect tables (don't use substituted new_database)
  219. # NOTE: v.db.connect creates an index on the key column
  220. try:
  221. gscript.run_command('v.db.connect', flags='o', quiet=True,
  222. map=vect, layer=layer,
  223. driver=new_driver,
  224. database=new_database,
  225. table=new_schema_table, key=key)
  226. except CalledModuleError:
  227. gscript.warning(_("Unable to connect table <%s> to vector "
  228. "<%s> on layer <%s>") %
  229. (table, vect, str(layer)))
  230. else:
  231. if database != new_database_subst:
  232. gscript.warning(_("Layer <%d> will not be reconnected "
  233. "because database or schema do not "
  234. "match.") % layer)
  235. return 0
  236. if __name__ == "__main__":
  237. options, flags = gscript.parser()
  238. nuldev = open(os.devnull, 'w')
  239. sys.exit(main())