#!/bin/sh # ############################################################################ # # MODULE: v.db.addtable # AUTHOR(S): Markus Neteler # PURPOSE: interface to db.execute to creates and add a new table to given vector map # COPYRIGHT: (C) 2005 by 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: creates and adds a new attribute table to a given layer of an existing vector map #% keywords: vector, database, attribute table #%End #%option #% key: map #% type: string #% gisprompt: old,vector,vector #% description: Vector map for which to add new attribute table #% required : yes #% key_desc : name #%end #%option #% key: table #% type: string #% description: Name of new attribute table (default: vector map name) #% required : no #%end #%option #% key: layer #% type: integer #% description: Layer where to add new attribute table #% answer: 1 #% required : no #%end #%option #% key: columns #% type: string #% description: Name and type of the new column(s) (types depend on database backend, but all support VARCHAR(), INT, DOUBLE and DATE) #% answer: cat integer #% required : no #% multiple : yes #% key_desc : name type #%end if [ -z "$GISBASE" ] ; then echo "You must be in GRASS GIS to run this program." 1>&2 exit 1 fi if [ "$1" != "@ARGS_PARSED@" ] ; then exec g.parser "$0" "$@" fi PROG=`basename $0` #### check if we have awk if [ ! -x "`which awk`" ] ; then echo "$PROG: awk required, please install awk or gawk first" 1>&2 exit 1 fi # setting environment, so that awk works properly in all languages unset LC_ALL LC_NUMERIC=C export LC_NUMERIC if [ -z "$GIS_OPT_TABLE" ] ; then if [ $GIS_OPT_LAYER -eq 1 ] ; then echo "Using vector map name as table name: ${GIS_OPT_MAP}" 1>&2 table=${GIS_OPT_MAP} else # two avoid tables with identical names on higher layers echo "Using vector map name extended by layer number as table name: ${GIS_OPT_MAP}_$GIS_OPT_LAYER" 1>&2 table=${GIS_OPT_MAP}_$GIS_OPT_LAYER fi else echo "Using user specified table name: $GIS_OPT_TABLE" table=$GIS_OPT_TABLE fi # we use the DB settings of layer 1 to find out default connection QUERYLAYER=1 #check if anything is connected: v.db.connect $GIS_OPT_MAP -g layer=1 2> /dev/null | grep '^1 ' > /dev/null if [ $? -ne 0 ] ; then # nothing defined for layer 1 echo "Creating new DB connection based on default mapset settings..." 1>&2 database=`db.connect -p | grep database | cut -d':' -f2` if [ $? -ne 0 ] ; then # this tests the result of cut? what if "(null)"? grep -v '(null)'? echo "An error occured. Stop." 1>&2 exit 1 fi driver=`db.connect -p | grep driver | cut -d':' -f2` if [ "$driver" = "(null)" ] || [ "$database" = "(null)" ] ; then echo "Setting default database driver to DBF." 1>&2 database='$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/' driver=dbf db.connect driver=$driver database=$database fi else # there is a definition for layer 1, so we check for the user defined layer database=`v.db.connect $GIS_OPT_MAP -g | grep -w $QUERYLAYER | awk '{print $4}'` if [ -z "database" ] ; then #nothing on user defined layer, so we use the default mapset settings in this case: database=`db.connect -p | grep database | cut -d':' -f2` driver=`db.connect -p | grep driver | cut -d':' -f2` else driver=`v.db.connect $GIS_OPT_MAP -g | grep -w $QUERYLAYER | awk '{print $5}'` fi fi #maybe there is already a table linked to the selected layer? if [ $GIS_OPT_LAYER -eq 1 ] ; then v.db.connect $GIS_OPT_MAP -g 2> /dev/null | grep -w $GIS_OPT_LAYER > /dev/null if [ $? -eq 0 ] ; then echo "ERROR: there is already a table linked to layer <$GIS_OPT_LAYER>" 1>&2 exit 1 fi fi #maybe there is already a table with that name? db.tables database=$database driver=$driver 2> /dev/null | grep "^$table$" if [ $? -ne 0 ] ; then #if not existing, create it: if [ "$GIS_OPT_COLUMNS" = "cat integer" ] ; then COLUMN_DEF="cat integer" else COLUMN_DEF=`echo "cat integer, $GIS_OPT_COLUMNS" | sed \ -e 's/cat integer, cat integer,/cat integer, /' \ -e 's/cat integer, cat INTEGER,/cat integer, /' \ -e 's/cat integer, cat int,/cat integer, /' \ -e 's/cat integer, cat INT,/cat integer, /'` fi echo "Creating table with columns ($COLUMN_DEF)" 1>&2 echo "CREATE TABLE $table ($COLUMN_DEF)" | db.execute database=$database driver=$driver if [ $? -ne 0 ] ; then # take care if no DB was ever defined (e.g., in a new mapset) # probably the DBF directory is missing (heck, the DBF driver should take care!) echo "CREATE TABLE $table ($COLUMN_DEF)" | db.execute database=$database \ driver=$driver | grep 'Cannot open dbf database' if [ $? -ne 0 ] ; then GISDBASE=`g.gisenv GISDBASE` LOCATION_NAME=`g.gisenv LOCATION_NAME` MAPSET=`g.gisenv MAPSET` echo "Creating missing DBF directory in MAPSET <${MAPSET}>" 1>&2 mkdir -p ${GISDBASE}/${LOCATION_NAME}/${MAPSET}/dbf db.connect driver=dbf database='$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/' echo "CREATE TABLE $table ($COLUMN_DEF)" | db.execute if [ $? -ne 0 ] ; then echo "An error occured. Stop." 1>&2 exit 1 fi fi fi else echo "ERROR: A table of the name <$table> already exists in <$database>." 1>&2 exit 1 fi # connect the map to the DB: v.db.connect map=$GIS_OPT_MAP database=$database driver=$driver layer=$GIS_OPT_LAYER table=$table key=cat # finally we have to add cats into the attribute DB to make modules such as v.what.rast happy: # (creates new row for each vector line): v.to.db $GIS_OPT_MAP layer=$GIS_OPT_LAYER option=cat col=cat echo "" 1>&2 echo "Current attribute table links:" 1>&2 v.db.connect -p $GIS_OPT_MAP exit 0