db.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. """!@package grass.script.db
  2. @brief GRASS Python scripting module (database functions)
  3. Database related functions to be used in Python scripts.
  4. Usage:
  5. @code
  6. from grass.script import db as grass
  7. grass.db_describe(table)
  8. ...
  9. @endcode
  10. (C) 2008-2009, 2012 by the GRASS Development Team
  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. @author Glynn Clements
  15. @author Martin Landa <landa.martin gmail.com>
  16. """
  17. import tempfile as pytempfile # conflict with core.tempfile
  18. from core import *
  19. from utils import try_remove
  20. def db_describe(table, **args):
  21. """!Return the list of columns for a database table
  22. (interface to `db.describe -c'). Example:
  23. \code
  24. >>> grass.db_describe('lakes')
  25. {'nrows': 15279, 'cols': [['cat', 'INTEGER', '11'], ['AREA', 'DOUBLE PRECISION', '20'],
  26. ['PERIMETER', 'DOUBLE PRECISION', '20'], ['FULL_HYDRO', 'DOUBLE PRECISION', '20'],
  27. ['FULL_HYDR2', 'DOUBLE PRECISION', '20'], ['FTYPE', 'CHARACTER', '24'],
  28. ['FCODE', 'INTEGER', '11'], ['NAME', 'CHARACTER', '99']], 'ncols': 8}
  29. \endcode
  30. @param table table name
  31. @param args
  32. @return parsed module output
  33. """
  34. s = read_command('db.describe', flags = 'c', table = table, **args)
  35. if not s:
  36. fatal(_("Unable to describe table <%s>") % table)
  37. cols = []
  38. result = {}
  39. for l in s.splitlines():
  40. f = l.split(':')
  41. key = f[0]
  42. f[1] = f[1].lstrip(' ')
  43. if key.startswith('Column '):
  44. n = int(key.split(' ')[1])
  45. cols.insert(n, f[1:])
  46. elif key in ['ncols', 'nrows']:
  47. result[key] = int(f[1])
  48. else:
  49. result[key] = f[1:]
  50. result['cols'] = cols
  51. return result
  52. # run "db.connect -g" and parse output
  53. def db_table_exist(table, **args):
  54. """!Check if table exists.
  55. If no driver or database are given, then default settings is used
  56. (check db_connection()).
  57. @param table table name
  58. @param driver DB driver
  59. @param database DB to check
  60. @return True for success, False otherwise
  61. """
  62. nuldev = file(os.devnull, 'w+')
  63. ret = run_command('db.describe', flags = 'c', table = table,
  64. stdout = nuldev, stderr = nuldev, **args)
  65. nuldev.close()
  66. if ret == 0:
  67. return True
  68. return False
  69. def db_connection(force=False):
  70. """!Return the current database connection parameters
  71. (interface to `db.connect -g'). Example:
  72. \code
  73. >>> grass.db_connection()
  74. {'group': 'x', 'schema': '', 'driver': 'dbf', 'database': '$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/'}
  75. \endcode
  76. :param force True to set up default DB connection if not defined
  77. :return: parsed output of db.connect
  78. """
  79. nuldev = file(os.devnull, 'w')
  80. conn = parse_command('db.connect', flags='g', stderr=nuldev)
  81. nuldev.close()
  82. if not conn['driver'] and force:
  83. run_command('db.connect', flags='c')
  84. conn = parse_command('db.connect', flags='g')
  85. return conn
  86. def db_select(sql = None, filename = None, table = None, **args):
  87. """!Perform SQL select statement
  88. Note: one of <em>sql</em>, <em>filename</em>, or <em>table</em>
  89. arguments must be provided.
  90. Examples:
  91. \code
  92. grass.db_select(sql = 'SELECT cat,CAMPUS FROM busstopsall WHERE cat < 4')
  93. (('1', 'Vet School'), ('2', 'West'), ('3', 'North'))
  94. \endcode
  95. \code
  96. grass.db_select(filename = '/path/to/sql/file')
  97. \endcode
  98. Simplyfied usage
  99. \code
  100. grass.db_select(table = 'busstopsall')
  101. \endcode
  102. performs <tt>SELECT * FROM busstopsall</tt>.
  103. @param sql SQL statement to perform (or None)
  104. @param filename name of file with SQL statements (or None)
  105. @param table name of table to query (or None)
  106. @param args see \gmod{db.select} arguments
  107. """
  108. fname = tempfile(create = False)
  109. if sql:
  110. args['sql'] = sql
  111. elif filename:
  112. args['input'] = filename
  113. elif table:
  114. args['table'] = table
  115. else:
  116. fatal(_("Programmer error: '%(sql)s', '%(filename)s', or '%(table)s' must be provided") %
  117. {'sql': 'sql', 'filename': 'filename', 'table': 'table'} )
  118. if 'sep' not in args:
  119. args['sep'] = '|'
  120. ret = run_command('db.select', quiet = True,
  121. flags = 'c',
  122. output = fname,
  123. **args)
  124. if ret != 0:
  125. fatal(_("Fetching data failed"))
  126. ofile = open(fname)
  127. result = map(lambda x: tuple(x.rstrip(os.linesep).split(args['sep'])),
  128. ofile.readlines())
  129. ofile.close()
  130. try_remove(fname)
  131. return tuple(result)
  132. def db_table_in_vector(table):
  133. """Return the name of vector connected to the table.
  134. It returns False if no vectors are connected to the table.
  135. Example
  136. @params table name of table to query
  137. """
  138. from vector import vector_db
  139. nuldev = file(os.devnull, 'w')
  140. used = []
  141. vects = list_strings('vect')
  142. for vect in vects:
  143. for f in vector_db(vect, stderr=nuldev).itervalues():
  144. if not f:
  145. continue
  146. if f['table'] == table:
  147. used.append(vect)
  148. break
  149. return used