v.db.addtable.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #!/usr/bin/env python
  2. #
  3. ############################################################################
  4. #
  5. # MODULE: v.db.addtable
  6. # AUTHOR(S): Markus Neteler
  7. # Converted to Python by Glynn Clements
  8. # Key column added by Martin Landa <landa.martin gmail.com>
  9. # Table index added by Markus Metz
  10. # PURPOSE: interface to db.execute to creates and add a new table to given vector map
  11. # COPYRIGHT: (C) 2005, 2007, 2008, 2011 by Markus Neteler & the GRASS Development Team
  12. #
  13. # This program is free software under the GNU General Public
  14. # License (>=v2). Read the file COPYING that comes with GRASS
  15. # for details.
  16. #
  17. #############################################################################
  18. #%module
  19. #% description: Creates and connects a new attribute table to a given layer of an existing vector map.
  20. #% keyword: vector
  21. #% keyword: attribute table
  22. #% keyword: database
  23. #%end
  24. #%option G_OPT_V_MAP
  25. #%end
  26. #%option
  27. #% key: table
  28. #% type: string
  29. #% description: Name of new attribute table (default: vector map name)
  30. #% required: no
  31. #% guisection: Definition
  32. #%end
  33. #%option
  34. #% key: layer
  35. #% type: integer
  36. #% description: Layer number where to add new attribute table
  37. #% answer: 1
  38. #% required: no
  39. #% guisection: Definition
  40. #%end
  41. #%option G_OPT_DB_KEYCOLUMN
  42. #% guisection: Definition
  43. #%end
  44. #%option
  45. #% key: columns
  46. #% type: string
  47. #% label: Name and type of the new column(s) ('name type [,name type, ...]')
  48. #% description: Types depend on database backend, but all support VARCHAR(), INT, DOUBLE PRECISION and DATE. Example: 'label varchar(250), value integer'
  49. #% required: no
  50. #% multiple: yes
  51. #% key_desc: name type
  52. #% guisection: Definition
  53. #%end
  54. import sys
  55. import os
  56. import grass.script as grass
  57. from grass.script.utils import decode
  58. from grass.exceptions import CalledModuleError
  59. def main():
  60. vector = options['map']
  61. table = options['table']
  62. layer = options['layer']
  63. columns = options['columns']
  64. key = options['key']
  65. # does map exist in CURRENT mapset?
  66. mapset = grass.gisenv()['MAPSET']
  67. if not grass.find_file(vector, element='vector', mapset=mapset)['file']:
  68. grass.fatal(_("Vector map <%s> not found in current mapset") % vector)
  69. map_name = vector.split('@')[0]
  70. if not table:
  71. if layer == '1':
  72. grass.verbose(_("Using vector map name as table name: <%s>") % map_name)
  73. table = map_name
  74. else:
  75. # to avoid tables with identical names on higher layers
  76. table = "%s_%s" % (map_name, layer)
  77. grass.verbose(
  78. _("Using vector map name extended by layer number as table name: <%s>") %
  79. table)
  80. else:
  81. grass.verbose(_("Using user specified table name: %s") % table)
  82. # check if DB parameters are set, and if not set them.
  83. grass.run_command('db.connect', flags='c', quiet=True)
  84. grass.verbose(_("Creating new DB connection based on default mapset settings..."))
  85. kv = grass.db_connection()
  86. database = kv['database']
  87. driver = kv['driver']
  88. schema = kv['schema']
  89. database2 = database.replace('$MAP/', map_name + '/')
  90. # maybe there is already a table linked to the selected layer?
  91. nuldev = open(os.devnull, 'w')
  92. try:
  93. grass.vector_db(map_name, stderr=nuldev)[int(layer)]
  94. grass.fatal(_("There is already a table linked to layer <%s>") % layer)
  95. except KeyError:
  96. pass
  97. # maybe there is already a table with that name?
  98. tables = grass.read_command('db.tables', flags='p', database=database2, driver=driver,
  99. stderr=nuldev)
  100. tables = decode(tables)
  101. if not table in tables.splitlines():
  102. colnames = []
  103. column_def = []
  104. if columns:
  105. column_def = []
  106. for x in ' '.join(columns.split()).split(','):
  107. colname = x.lower().split()[0]
  108. if colname in colnames:
  109. grass.fatal(_("Duplicate column name '%s' not allowed") % colname)
  110. colnames.append(colname)
  111. column_def.append(x)
  112. # if not existing, create it:
  113. if not key in colnames:
  114. column_def.insert(0, "%s integer" % key)
  115. column_def = ','.join(column_def)
  116. grass.verbose(_("Creating table with columns (%s)...") % column_def)
  117. sql = "CREATE TABLE %s (%s)" % (table, column_def)
  118. try:
  119. grass.run_command('db.execute',
  120. database=database2, driver=driver, sql=sql)
  121. except CalledModuleError:
  122. grass.fatal(_("Unable to create table <%s>") % table)
  123. # connect the map to the DB:
  124. if schema:
  125. table = '{schema}.{table}'.format(schema=schema, table=table)
  126. grass.verbose(_("Connecting new table to vector map <%s>...") % map_name)
  127. grass.run_command('v.db.connect', quiet=True,
  128. map=map_name, database=database, driver=driver,
  129. layer=layer, table=table, key=key)
  130. # finally we have to add cats into the attribute DB to make
  131. # modules such as v.what.rast happy: (creates new row for each
  132. # vector line):
  133. try:
  134. grass.run_command('v.to.db', map=map_name, layer=layer,
  135. option='cat', column=key, qlayer=layer)
  136. except CalledModuleError:
  137. # remove link
  138. grass.run_command('v.db.connect', quiet=True, flags='d',
  139. map=map_name, layer=layer)
  140. return 1
  141. grass.verbose(_("Current attribute table links:"))
  142. if grass.verbosity() > 2:
  143. grass.run_command('v.db.connect', flags='p', map=map_name)
  144. # write cmd history:
  145. grass.vector_history(map_name)
  146. return 0
  147. if __name__ == "__main__":
  148. options, flags = grass.parser()
  149. sys.exit(main())