123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- #!/usr/bin/env python
- ############################################################################
- #
- # MODULE: v.db.join
- # AUTHOR(S): Markus Neteler
- # Converted to Python by Glynn Clements
- # PURPOSE: Join a table to a map table
- # COPYRIGHT: (C) 2007-2009 by Markus Neteler and the GRASS Development Team
- #
- # This program is free software under the GNU General Public
- # License (>=v2). Read the file COPYING that comes with GRASS
- # for details.
- #
- #############################################################################
- #%module
- #% description: Allows to join a table to a vector map table.
- #% keywords: vector
- #% keywords: attribute table
- #% keywords: database
- #%end
- #%option G_OPT_V_MAP
- #% description: Vector map to which to join other table
- #% guidependency: layer,column
- #%end
- #%option G_OPT_V_FIELD
- #% description: Layer where to join
- #% guidependency: column
- #%end
- #%option G_OPT_DB_COLUMN
- #% description: Identifier column (e.g.: cat) in the vector table to be used for join
- #% required : yes
- #%end
- #%option G_OPT_DB_TABLE
- #% key: otable
- #% description: Other table name
- #% required: yes
- #% guidependency: ocolumn,scolumns
- #%end
- #%option G_OPT_DB_COLUMN
- #% key: ocolumn
- #% description: Identifier column (e.g.: id) in the other table used for join
- #% required: yes
- #%end
- #%option G_OPT_DB_COLUMN
- #% key: scolumns
- #% multiple: yes
- #% required: no
- #% description: Subset of columns from the other table
- #%end
- import sys
- import os
- import string
- import grass.script as grass
- def main():
- map = options['map']
- layer = options['layer']
- column = options['column']
- otable = options['otable']
- ocolumn = options['ocolumn']
- if options['scolumns']:
- scolumns = options['scolumns'].split(',')
- else:
- scolumns = None
-
- f = grass.vector_layer_db(map, layer)
- maptable = f['table']
- database = f['database']
- driver = f['driver']
- if driver == 'dbf':
- grass.fatal(_("JOIN is not supported for tables stored in DBF format"))
- if not maptable:
- grass.fatal(_("There is no table connected to this map. Unable to join any column."))
- # check if column is in map table
- if not grass.vector_columns(map, layer).has_key(column):
- grass.fatal(_("Column <%s> not found in table <%s>") % (column, maptable))
- # describe other table
- all_cols_ot = grass.db_describe(otable, driver = driver, database = database)['cols']
- # check if ocolumn is on other table
- if ocolumn not in [ocol[0] for ocol in all_cols_ot]:
- grass.fatal(_("Column <%s> not found in table <%s>") % (ocolumn, otable))
- # determine columns subset from other table
- if not scolumns:
- # select all columns from other table
- cols_to_add = all_cols_ot
- else:
- cols_to_add = []
- # check if scolumns exists in the other table
- for scol in scolumns:
- found = False
- for col_ot in all_cols_ot:
- if scol == col_ot[0]:
- found = True
- cols_to_add.append(col_ot)
- break
- if not found:
- grass.warning(_("Column <%s> not found in table <%s>.") % (scol, otable))
-
- all_cols_tt = grass.vector_columns(map, int(layer)).keys()
- select = "SELECT $colname FROM $otable WHERE $otable.$ocolumn=$table.$column"
- template = string.Template("UPDATE $table SET $colname=(%s);" % select)
- for col in cols_to_add:
- # skip the vector column which is used for join
- colname = col[0]
- if colname == column:
- continue
- # Sqlite 3 does not support the precision number any more
- if len(col) > 2 and driver != "sqlite":
- coltype = "%s(%s)" % (col[1], col[2])
- else:
- coltype = "%s" % col[1]
- colspec = "%s %s" % (colname, coltype)
- # add only the new column to the table
- if colname not in all_cols_tt:
- if grass.run_command('v.db.addcolumn', map = map, columns = colspec, layer = layer) != 0:
- grass.fatal(_("Error creating column <%s>") % colname)
- stmt = template.substitute(table = maptable, column = column,
- otable = otable, ocolumn = ocolumn,
- colname = colname)
- grass.debug(stmt, 1)
- grass.verbose(_("Updating column <%s> of vector map <%s>...") % (colname, map))
- if grass.write_command('db.execute', stdin = stmt, input = '-', database = database, driver = driver) != 0:
- grass.fatal(_("Error filling column <%s>") % colname)
- # write cmd history
- grass.vector_history(map)
- return 0
- if __name__ == "__main__":
- options, flags = grass.parser()
- sys.exit(main())
|