def main(): map = options['map'] layer = options['layer'] column = options['column'] mapset = grass.gisenv()['MAPSET'] if not grass.find_file(map, element = 'vector', mapset = mapset): grass.fatal(_("Vector map <%s> not found in current mapset") % map) f = grass.vector_layer_db(map, layer) table = f['table'] keycol = f['key'] database = f['database'] driver = f['driver'] if not table: grass.fatal(_("There is no table connected to the input vector map. Cannot rename any column")) cols = column.split(',') oldcol = cols[0] newcol = cols[1] if driver == "dbf": if len(newcol) > 10: grass.fatal(_("Column name <%s> too long. The DBF driver supports column names not longer than 10 characters") % newcol) if oldcol == keycol: grass.fatal(_("Cannot rename column <%s> as it is needed to keep table <%s> connected to the input vector map") % (oldcol, table)) # describe old col oldcoltype = None for f in grass.db_describe(table)['cols']: if f[0] != oldcol: continue oldcoltype = f[1] oldcollength = f[2] # old col there? if not oldcoltype: grass.fatal(_("Column <%s> not found in table <%s>") % (oldcol, table)) # some tricks if driver in ['sqlite', 'dbf']: if oldcoltype.upper() == "CHARACTER": colspec = "%s varchar(%s)" % (newcol, oldcollength) else: colspec = "%s %s" % (newcol, oldcoltype) grass.run_command('v.db.addcolumn', map = map, layer = layer, column = colspec) sql = "UPDATE %s SET %s=%s" % (table, newcol, oldcol) grass.write_command('db.execute', input = '-', database = database, driver = driver, stdin = sql) grass.run_command('v.db.dropcolumn', map = map, layer = layer, column = oldcol) else: sql = "ALTER TABLE %s RENAME %s TO %s" % (table, oldcol, newcol) grass.write_command('db.execute', input = '-', database = database, driver = driver, stdin = sql) # write cmd history: grass.vector_history(map)
def get_table_name(map_name, layer): ### Test to make sure the vector has the correct layer - and get the table name from it try: table_name = grass.vector_layer_db(map_name, layer)['name'] except: grass.fatal("Map <%s> does not have layer number %s" % (map_name,layer)) return table_name
def get_table_name(map_name, layer): ### Test to make sure the vector has the correct layer - and get the table name from it try: table_name = grass.vector_layer_db(map_name, layer)['name'] except: grass.fatal("Map <%s> does not have layer number %s" % (map_name, layer)) return table_name
def main(): options, flags = gscript.parser() inputmap = options['input'] layer = options['layer'] outputmap = options['output'] sort_column = options['column'] reverse = True if flags['r']: reverse = False columns = gscript.vector_columns(inputmap) key_column = gscript.vector_layer_db(inputmap, layer)['key'] sort_index = columns[sort_column]['index']+2 sorted_cols = sorted(iter(columns.items()), key=lambda x_y: x_y[1]['index']) column_def="x DOUBLE PRECISION, y DOUBLE PRECISION, cat INTEGER" colnames = [] for colcount in range(1,len(sorted_cols)): name = sorted_cols[colcount][0] type = sorted_cols[colcount][1]['type'] if name == sort_column and (type != 'INTEGER' and type != 'DOUBLE PRECISION'): gscript.fatal('Sort column must be numeric') if name == key_column: continue colnames.append(name) column_def += ", %s %s" % (name, type) inpoints=gscript.read_command('v.out.ascii', in_=inputmap, columns=colnames, quiet=True) points=[] for line in inpoints.splitlines(): data = [num(x) for x in line.split('|')] points.append(data) points_sorted=sorted(points, key=lambda x: x[sort_index], reverse=reverse) outpoints = "" for list in points_sorted: outpoints+="|".join([str(x) for x in list])+"\n" gscript.write_command('v.in.ascii', input='-', stdin=outpoints, output=outputmap, x=1, y=2, cat=3, columns=column_def, quiet=True) gscript.run_command('v.db.dropcolumn', map=outputmap, columns='x,y', quiet=True) return 0
def main(): force = flags['f'] map = options['map'] table = options['table'] layer = options['layer'] # do some paranoia tests as well: f = gscript.vector_layer_db(map, layer) if not table: # Removing table name connected to selected layer table = f['table'] if not table: gscript.fatal(_("No table assigned to layer <%s>") % layer) else: # Removing user specified table existingtable = f['table'] if existingtable != table: gscript.fatal(_("User selected table <%s> but the table <%s> " "is linked to layer <%s>") % (table, existingtable, layer)) # we use the DB settings selected layer database = f['database'] driver = f['driver'] gscript.message(_("Removing table <%s> linked to layer <%s> of vector" " map <%s>") % (table, layer, map)) if not force: gscript.message(_("You must use the -f (force) flag to actually " "remove the table. Exiting.")) gscript.message(_("Leaving map/table unchanged.")) sys.exit(0) gscript.message(_("Dropping table <%s>...") % table) try: gscript.write_command('db.execute', stdin="DROP TABLE %s" % table, input='-', database=database, driver=driver) except CalledModuleError: gscript.fatal(_("An error occurred while running db.execute")) gscript.run_command('v.db.connect', flags='d', map=map, layer=layer) gscript.message(_("Current attribute table link(s):")) # silently test first to avoid confusing error messages nuldev = open(os.devnull, 'w') try: gscript.run_command('v.db.connect', flags='p', map=map, quiet=True, stdout=nuldev, stderr=nuldev) except CalledModuleError: gscript.message(_("(No database links remaining)")) else: gscript.run_command('v.db.connect', flags='p', map=map) # write cmd history: gscript.vector_history(map)
def main(): map = options['map'] layer = options['layer'] column = options['column'] otable = options['otable'] ocolumn = options['ocolumn'] 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.")) if not grass.vector_columns(map, layer).has_key(column): grass.fatal(_("Column <%s> not found in table <%s> at layer <%s>") % (column, map, layer)) all_cols_ot = grass.db_describe(otable, driver = driver, database = database)['cols'] 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 all_cols_ot: # 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.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)
def main(): force = flags['f'] map = options['map'] table = options['table'] layer = options['layer'] # do some paranoia tests as well: f = grass.vector_layer_db(map, layer) if not table: # Removing table name connected to selected layer table = f['table'] if not table: grass.fatal(_("No table assigned to layer <%s>") % layer) else: # Removing user specified table existingtable = f['table'] if existingtable != table: grass.fatal(_("User selected table <%s> but the table <%s> is linked to layer <%s>") % (table, existingtable, layer)) # we use the DB settings selected layer database = f['database'] driver = f['driver'] grass.message(_("Removing table <%s> linked to layer <%s> of vector map <%s>") % (table, layer, map)) if not force: grass.message(_("You must use the -f (force) flag to actually remove the table. Exiting.")) grass.message(_("Leaving map/table unchanged.")) sys.exit(0) grass.message(_("Dropping table <%s>...") % table) try: grass.write_command('db.execute', stdin="DROP TABLE %s" % table, input='-', database=database, driver=driver) except CalledModuleError: grass.fatal(_("An error occurred while running db.execute")) grass.run_command('v.db.connect', flags = 'd', map = map, layer = layer) grass.message(_("Current attribute table link(s):")) # silently test first to avoid confusing error messages nuldev = file(os.devnull, 'w') try: grass.run_command('v.db.connect', flags='p', map=map, quiet=True, stdout=nuldev, stderr=nuldev) except CalledModuleError: grass.message(_("(No database links remaining)")) else: grass.run_command('v.db.connect', flags='p', map=map) # write cmd history: grass.vector_history(map)
def main(): global output, tmp input = options['input'] output = options['output'] layer = options['layer'] column = options['column'] # setup temporary file tmp = str(os.getpid()) # does map exist? if not grass.find_file(input, element='vector')['file']: grass.fatal(_("Vector map <%s> not found") % input) if not column: grass.warning( _("No '%s' option specified. Dissolving based on category values from layer <%s>.") % ("column", layer)) grass.run_command('v.extract', flags='d', input=input, output=output, type='area', layer=layer) else: if int(layer) == -1: grass.warning(_("Invalid layer number (%d). " "Parameter '%s' specified, assuming layer '1'.") % (int(layer), 'column')) layer = '1' try: coltype = grass.vector_columns(input, layer)[column] except KeyError: grass.fatal(_('Column <%s> not found') % column) if coltype['type'] not in ('INTEGER', 'SMALLINT', 'CHARACTER', 'TEXT'): grass.fatal(_("Key column must be of type integer or string")) f = grass.vector_layer_db(input, layer) table = f['table'] tmpfile = '%s_%s' % (output, tmp) try: grass.run_command('v.reclass', input=input, output=tmpfile, layer=layer, column=column) grass.run_command('v.extract', flags='d', input=tmpfile, output=output, type='area', layer=layer) except CalledModuleError as e: grass.fatal(_("Final extraction steps failed." " Check above error messages and" " see following details:\n%s") % e) # write cmd history: grass.vector_history(output)
def main(): global output, tmp input = options['input'] output = options['output'] layer = options['layer'] column = options['column'] #### setup temporary file tmp = str(os.getpid()) # does map exist? if not grass.find_file(input, element = 'vector')['file']: grass.fatal(_("Vector map <%s> not found") % input) if not column: grass.run_command('v.extract', flags = 'd', input = input, output = output, type = 'area', layer = layer) else: try: coltype = grass.vector_columns(input, layer)[column] except KeyError: grass.fatal(_('Column <%s> not found') % column) if coltype['type'] not in ('INTEGER', 'CHARACTER'): grass.fatal(_("Key column must be of type integer or string")) f = grass.vector_layer_db(input, layer) table = f['table'] tmpfile = '%s_%s' % (output, tmp) if grass.run_command('v.reclass', input = input, output = tmpfile, layer = layer, column = column) == 0: grass.run_command('v.extract', flags = 'd', input = tmpfile, output = output, type = 'area', layer = layer) # write cmd history: grass.vector_history(output)
def main(): force = flags["f"] map = options["map"] table = options["table"] layer = options["layer"] # We check for existence of the map in the current mapset before # doing any other operation. info = gscript.find_file(map, element="vector", mapset=".") if not info["file"]: mapset = gscript.gisenv()["MAPSET"] # Message is formulated in the way that it does not mislead # in case where a map of the same name is in another mapset. gscript.fatal( _("Vector map <{name}> not found" " in the current mapset ({mapset})").format(name=map, mapset=mapset)) # do some paranoia tests as well: f = gscript.vector_layer_db(map, layer) if not table: # Removing table name connected to selected layer table = f["table"] if not table: gscript.fatal(_("No table assigned to layer <%s>") % layer) else: # Removing user specified table existingtable = f["table"] if existingtable != table: gscript.fatal( _("User selected table <%s> but the table <%s> " "is linked to layer <%s>") % (table, existingtable, layer)) # we use the DB settings selected layer database = f["database"] driver = f["driver"] gscript.message( _("Removing table <%s> linked to layer <%s> of vector" " map <%s>") % (table, layer, map)) if not force: gscript.message( _("You must use the -f (force) flag to actually " "remove the table. Exiting.")) gscript.message(_("Leaving map/table unchanged.")) sys.exit(0) gscript.message(_("Dropping table <%s>...") % table) try: gscript.write_command( "db.execute", stdin="DROP TABLE %s" % table, input="-", database=database, driver=driver, ) except CalledModuleError: gscript.fatal(_("An error occurred while running db.execute")) gscript.run_command("v.db.connect", flags="d", map=map, layer=layer) gscript.message(_("Current attribute table link(s):")) # silently test first to avoid confusing error messages nuldev = open(os.devnull, "w") try: gscript.run_command("v.db.connect", flags="p", map=map, quiet=True, stdout=nuldev, stderr=nuldev) except CalledModuleError: gscript.message(_("(No database links remaining)")) else: gscript.run_command("v.db.connect", flags="p", map=map) # write cmd history: gscript.vector_history(map)
def main(): map = options['map'] layer = options['layer'] columns = options['columns'].split(',') mapset = grass.gisenv()['MAPSET'] # does map exist in CURRENT mapset? if not grass.find_file(map, element='vector', mapset=mapset)['file']: grass.fatal(_("Vector map <%s> not found in current mapset") % map) f = grass.vector_layer_db(map, layer) table = f['table'] keycol = f['key'] database = f['database'] driver = f['driver'] if not table: grass.fatal(_("There is no table connected to the input vector map. " "Unable to delete any column. Exiting.")) if keycol in columns: grass.fatal(_("Unable to delete <%s> column as it is needed to keep table <%s> " "connected to the input vector map <%s>") % (keycol, table, map)) for column in columns: if column not in grass.vector_columns(map, layer): grass.warning(_("Column <%s> not found in table <%s>. Skipped") % (column, table)) continue if driver == "sqlite": # echo "Using special trick for SQLite" # http://www.sqlite.org/faq.html#q11 colnames = [] coltypes = [] for f in grass.db_describe(table, database=database, driver=driver)['cols']: if f[0] == column: continue colnames.append(f[0]) coltypes.append("%s %s" % (f[0], f[1])) colnames = ", ".join(colnames) coltypes = ", ".join(coltypes) cmds = [ "BEGIN TRANSACTION", "CREATE TEMPORARY TABLE ${table}_backup(${coldef})", "INSERT INTO ${table}_backup SELECT ${colnames} FROM ${table}", "DROP TABLE ${table}", "CREATE TABLE ${table}(${coldef})", "INSERT INTO ${table} SELECT ${colnames} FROM ${table}_backup", "CREATE UNIQUE INDEX ${table}_cat ON ${table} (${keycol} )", "DROP TABLE ${table}_backup", "COMMIT" ] tmpl = string.Template(';\n'.join(cmds)) sql = tmpl.substitute(table=table, coldef=coltypes, colnames=colnames, keycol=keycol) else: sql = "ALTER TABLE %s DROP COLUMN %s" % (table, column) try: grass.write_command('db.execute', input='-', database=database, driver=driver, stdin=sql) except CalledModuleError: grass.fatal(_("Deleting column failed")) # write cmd history: grass.vector_history(map)
def main(): global output, tmp input = options["input"] output = options["output"] layer = options["layer"] column = options["column"] # setup temporary file tmp = str(os.getpid()) # does map exist? if not grass.find_file(input, element="vector")["file"]: grass.fatal(_("Vector map <%s> not found") % input) if not column: grass.warning( _("No '%s' option specified. Dissolving based on category values from layer <%s>." ) % ("column", layer)) grass.run_command("v.extract", flags="d", input=input, output=output, type="area", layer=layer) else: if int(layer) == -1: grass.warning( _("Invalid layer number (%d). " "Parameter '%s' specified, assuming layer '1'.") % (int(layer), "column")) layer = "1" try: coltype = grass.vector_columns(input, layer)[column] except KeyError: grass.fatal(_("Column <%s> not found") % column) if coltype["type"] not in ("INTEGER", "SMALLINT", "CHARACTER", "TEXT"): grass.fatal(_("Key column must be of type integer or string")) f = grass.vector_layer_db(input, layer) table = f["table"] tmpfile = "%s_%s" % (output, tmp) try: grass.run_command("v.reclass", input=input, output=tmpfile, layer=layer, column=column) grass.run_command( "v.extract", flags="d", input=tmpfile, output=output, type="area", layer=layer, ) except CalledModuleError as e: grass.fatal( _("Final extraction steps failed." " Check above error messages and" " see following details:\n%s") % e) # write cmd history: grass.vector_history(output)
def main(): # Get the options input = options["input"] timestamp_column = options["timestamp_column"] columns = options["column"] layer = options["layer"] where = options["where"] strds = options["strds"] tempwhere = options["t_where"] i_flag = flags["i"] if where == "" or where == " " or where == "\n": where = None # overwrite = grass.overwrite() # Set verbosity level # quiet = True # if grass.verbosity() > 2: # quiet = False grass.warning(_('This addon is experimental!')) # Check DB connection for input vector map dbcon = grass.vector_layer_db(input, layer) # Check the number of sample strds and the number of columns strds_names = strds.split(",") column_names = columns.split(",") if not len(column_names) == len(strds_names): grass.fatal(_('Number of columns and number of STRDS does not match.')) # Check type of timestamp column cols = grass.vector_columns(input, layer=layer) if timestamp_column not in cols.keys(): grass.fatal( _('Could not find column {} \ in table connected to vector map {} \ at layer {}'.format(timestamp_column, input, layer))) if cols[timestamp_column]['type'] != 'DATE': if dbcon['driver'] != 'sqlite': # Note that SQLite does not have a DATE datatype and # and an index does not significantly speedup the process # (at least not with a couple of 100 points) grass.warning( _('Timestamp column is of type {}. \ It is recommended to use DATE type with an index. \ '.format(cols[timestamp_column]['type']))) # Make sure the temporal database exists tgis.init() # We need a database interface dbif = tgis.SQLDatabaseInterfaceConnection() dbif.connect() # Limit temporal extent to extent of points if no tempwhere is given if not tempwhere: extent = [] for stat in ('min', 'max'): tsql = "SELECT {}({}) FROM {}".format(stat, timestamp_column, dbcon['table']) extent.append(grass.read_command('db.select', flags='c', sql=tsql)) grass.verbose( _('Temporal extent of vector points map is \ {} to {}'.format(extent[0], extent[1]))) else: tempwhere = '({}) AND '.format(tempwhere) # Loop over STRDS counter = 0 for strds_name in strds_names: cur_strds = tgis.open_old_stds(strds_name, "strds", dbif) granu = cur_strds.get_granularity() start_time = tgis.datetime_math.check_datetime_string(extent[0]) start_gran = tgis.datetime_math.adjust_datetime_to_granularity( start_time, granu).isoformat() tempwhere += "(end_time > '{}' and start_time <= '{}')".format( start_gran, extent[1]) # needs to be set properly # Get info on registered maps in STRDS rows = cur_strds.get_registered_maps("name,mapset,start_time,end_time", tempwhere, "start_time", dbif) # Check temporal type and # define sampling function to use # becomes relevant when temporal type relative gets implemented if cur_strds.is_time_relative(): grass.fatal( _('Sorry, STRDS of relative temporal type is not (yet) supported' )) sample = sample_relative else: sample = sample_absolute # Check if there are raster maps to sample from that fullfill # temporal conditions if not rows and not tempwhere: dbif.close() grass.fatal( _("Space time raster dataset <%s> is empty".format( cur_strds.get_id()))) elif not rows and tempwhere: dbif.close() grass.fatal( _("No maps selected from Space time raster dataset <%s>, \ or dataset is empty".format(cur_strds.get_id()))) # Include temporal condition into where clause where_clause = '({}) AND '.format(where) if where else '' # Loop over registered maps in STRDS row_number = 0 for row in rows: # If r.what had a where option, r.what could be used to # collect raster values (without interpolation) # in a ParallelModuleQueue to collect values using multiple # cores and then upload results in one operation sample(input, layer, timestamp_column, column_names[counter], row, where_clause, i_flag) row_number += 1 grass.percent(row_number, len(rows), 3) counter = counter + 1 dbif.close() grass.vector_history(input)
def main(): options, flags = gscript.parser() inputmap = options["input"] layer = options["layer"] outputmap = options["output"] sort_column = options["column"] reverse = True if flags["r"]: reverse = False columns = gscript.vector_columns(inputmap) key_column = gscript.vector_layer_db(inputmap, layer)["key"] sort_index = columns[sort_column]["index"] + 2 sorted_cols = sorted(iter(columns.items()), key=lambda x_y: x_y[1]["index"]) column_def = "x DOUBLE PRECISION, y DOUBLE PRECISION, cat INTEGER" colnames = [] for colcount in range(1, len(sorted_cols)): name = sorted_cols[colcount][0] type = sorted_cols[colcount][1]["type"] if name == sort_column and (type != "INTEGER" and type != "DOUBLE PRECISION"): gscript.fatal("Sort column must be numeric") if name == key_column: continue colnames.append(name) column_def += ", %s %s" % (name, type) inpoints = gscript.read_command("v.out.ascii", in_=inputmap, columns=colnames, quiet=True) points = [] for line in inpoints.splitlines(): data = [num(x) for x in line.split("|")] points.append(data) points_sorted = sorted(points, key=lambda x: x[sort_index], reverse=reverse) outpoints = "" for list in points_sorted: outpoints += "|".join([str(x) for x in list]) + "\n" gscript.write_command( "v.in.ascii", input="-", stdin=outpoints, output=outputmap, x=1, y=2, cat=3, columns=column_def, quiet=True, ) gscript.run_command("v.db.dropcolumn", map=outputmap, columns="x,y", quiet=True) return 0
def main(): map = options["map"] layer = options["layer"] column = options["column"] otable = options["other_table"] ocolumn = options["other_column"] if options["subset_columns"]: scolumns = options["subset_columns"].split(",") else: scolumns = None try: f = grass.vector_layer_db(map, layer) except CalledModuleError: sys.exit(1) 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 column not in grass.vector_columns(map, layer): 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 use_len = False if len(col) > 2: use_len = True # Sqlite 3 does not support the precision number any more if driver == "sqlite": use_len = False # MySQL - expect format DOUBLE PRECISION(M,D), see #2792 elif driver == "mysql" and col[1] == "DOUBLE PRECISION": use_len = False if use_len: 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: try: grass.run_command("v.db.addcolumn", map=map, columns=colspec, layer=layer) except CalledModuleError: 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)) try: grass.write_command("db.execute", stdin=stmt, input="-", database=database, driver=driver) except CalledModuleError: grass.fatal(_("Error filling column <%s>") % colname) # write cmd history grass.vector_history(map) return 0
def main(): map = options['map'] layer = options['layer'] column = options['column'] mapset = grass.gisenv()['MAPSET'] if not grass.find_file(map, element='vector', mapset=mapset): grass.fatal(_("Vector map <%s> not found in current mapset") % map) f = grass.vector_layer_db(map, layer) table = f['table'] keycol = f['key'] database = f['database'] driver = f['driver'] if not table: grass.fatal( _("There is no table connected to the input vector map. Cannot rename any column" )) cols = column.split(',') oldcol = cols[0] newcol = cols[1] if driver == "dbf": if len(newcol) > 10: grass.fatal( _("Column name <%s> too long. The DBF driver supports column names not longer than 10 characters" ) % newcol) if oldcol == keycol: grass.fatal( _("Cannot rename column <%s> as it is needed to keep table <%s> connected to the input vector map" ) % (oldcol, table)) # describe old col oldcoltype = None for f in grass.db_describe(table)['cols']: if f[0] != oldcol: continue oldcoltype = f[1] oldcollength = f[2] # old col there? if not oldcoltype: grass.fatal(_("Column <%s> not found in table <%s>") % (oldcol, table)) # some tricks if driver in ['sqlite', 'dbf']: if oldcoltype.upper() == "CHARACTER": colspec = "%s varchar(%s)" % (newcol, oldcollength) else: colspec = "%s %s" % (newcol, oldcoltype) grass.run_command('v.db.addcolumn', map=map, layer=layer, column=colspec) sql = "UPDATE %s SET %s=%s" % (table, newcol, oldcol) grass.write_command('db.execute', input='-', database=database, driver=driver, stdin=sql) grass.run_command('v.db.dropcolumn', map=map, layer=layer, column=oldcol) elif driver == 'mysql': if oldcoltype.upper() == "CHARACTER": newcoltype = "varchar(%s)" % (oldcollength) else: newcoltype = oldcoltype sql = "ALTER TABLE %s CHANGE %s %s %s" % (table, oldcol, newcol, newcoltype) grass.write_command('db.execute', input='-', database=database, driver=driver, stdin=sql) else: sql = "ALTER TABLE %s RENAME %s TO %s" % (table, oldcol, newcol) grass.write_command('db.execute', input='-', database=database, driver=driver, stdin=sql) # write cmd history: grass.vector_history(map)
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