v.db.addtable.py 4.8 KB

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