v.db.addtable.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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. # PURPOSE: interface to db.execute to creates and add a new table to given vector map
  9. # COPYRIGHT: (C) 2005, 2007, 2008 by Markus Neteler & the GRASS Development Team
  10. #
  11. # This program is free software under the GNU General Public
  12. # License (>=v2). Read the file COPYING that comes with GRASS
  13. # for details.
  14. #
  15. #############################################################################
  16. #%Module
  17. #% description: Creates and connects a new attribute table to a given layer of an existing vector map.
  18. #% keywords: vector
  19. #% keywords: database
  20. #% keywords: attribute table
  21. #%End
  22. #%option
  23. #% key: map
  24. #% type: string
  25. #% gisprompt: old,vector,vector
  26. #% description: Vector map for which to add new attribute table
  27. #% required : yes
  28. #% key_desc : name
  29. #%end
  30. #%option
  31. #% key: table
  32. #% type: string
  33. #% description: Name of new attribute table (default: vector map name)
  34. #% required : no
  35. #%end
  36. #%option
  37. #% key: layer
  38. #% type: integer
  39. #% description: Layer where to add new attribute table
  40. #% answer: 1
  41. #% required : no
  42. #%end
  43. #%option
  44. #% key: columns
  45. #% type: string
  46. #% description: Name and type of the new column(s) (types depend on database backend, but all support VARCHAR(), INT, DOUBLE PRECISION and DATE)
  47. #% answer: cat integer
  48. #% required : no
  49. #% multiple : yes
  50. #% key_desc : name type
  51. #%end
  52. import sys
  53. import os
  54. import grass.script as grass
  55. def main():
  56. map = options['map']
  57. table = options['table']
  58. layer = options['layer']
  59. columns = options['columns']
  60. mapset = grass.gisenv()['MAPSET']
  61. # does map exist in CURRENT mapset?
  62. if not grass.find_file(map, element = 'vector', mapset = mapset)['file']:
  63. grass.fatal(_("Vector map <%s> not found in current mapset") % map)
  64. map_name = map.split('@')[0]
  65. if not table:
  66. if layer == '1':
  67. grass.message(_("Using vector map name as table name: ") + map_name)
  68. table = map_name
  69. else:
  70. # to avoid tables with identical names on higher layers
  71. grass.message(_("Using vector map name extended by layer number as table name: %s_%s") % (map_name, layer))
  72. table = "%s_%s" % (map_name, layer)
  73. else:
  74. grass.message(_("Using user specified table name: ") + table)
  75. # check if DB parameters are set, and if not set them.
  76. grass.run_command('db.connect', flags = 'c')
  77. grass.message(_("Creating new DB connection based on default mapset settings..."))
  78. kv = grass.db_connection()
  79. database = kv['database']
  80. driver = kv['driver']
  81. # maybe there is already a table linked to the selected layer?
  82. nuldev = file(os.devnull, 'w')
  83. try:
  84. grass.vector_db(map, stderr = nuldev)[int(layer)]
  85. grass.fatal(_("There is already a table linked to layer <%s>") % layer)
  86. except KeyError:
  87. pass
  88. # maybe there is already a table with that name?
  89. found = False
  90. p = grass.pipe_command('db.tables', database = database, driver = driver, stderr = nuldev)
  91. for line in p.stdout:
  92. if line.rstrip('\r\n') == table:
  93. found = True
  94. break
  95. p.wait()
  96. if not found:
  97. column_def = [col.strip().lower() for col in columns.split(',')]
  98. #if not existing, create it:
  99. if "cat integer" not in column_def:
  100. column_def.append("cat integer")
  101. column_def = ','.join(column_def)
  102. grass.message(_("Creating table with columns (%s)") % column_def)
  103. # take care if the DBF directory is missing (heck, the DBF driver should take care!)
  104. if driver == "dbf":
  105. env = grass.gisenv()
  106. path = os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], "dbf")
  107. if not os.path.isdir(path):
  108. grass.message(_("Creating missing DBF directory in mapset <%s>") % env['MAPSET'])
  109. os.mkdir(path)
  110. grass.run_command('db.connect', driver = dbf, database = '$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/')
  111. sql = "CREATE TABLE %s (%s)" % (table, column_def)
  112. if grass.write_command('db.execute', input = '-', database = database, driver = driver, stdin = sql) != 0:
  113. grass.fatal(_("Cannot continue."))
  114. # connect the map to the DB:
  115. grass.run_command('v.db.connect', map = map, database = database, driver = driver,
  116. layer = layer, table = table, key = 'cat')
  117. # finally we have to add cats into the attribute DB to make modules such as v.what.rast happy:
  118. # (creates new row for each vector line):
  119. grass.run_command('v.to.db', map = map, layer = layer,
  120. option = 'cat', column = 'cat', qlayer = layer)
  121. if grass.verbosity() > 0:
  122. grass.message(_("Current attribute table links:"))
  123. grass.run_command('v.db.connect', flags = 'p', map = map)
  124. # write cmd history:
  125. grass.vector_history(map)
  126. if __name__ == "__main__":
  127. options, flags = grass.parser()
  128. main()