base.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. """!@package grass.script.tgis_base
  2. @brief GRASS Python scripting module (temporal GIS functions)
  3. Temporal GIS base classes to be used in other
  4. Python temporal gis packages.
  5. This packages includes all base classes to stor basic information like id, name,
  6. mapset creation and modification time as well as sql serialization and deserialization
  7. and the sql database interface.
  8. Usage:
  9. @code
  10. import grass.temporal as tgis
  11. rbase = tgis.raster_base(ident="soil")
  12. ...
  13. @endcode
  14. (C) 2008-2011 by the GRASS Development Team
  15. This program is free software under the GNU General Public
  16. License (>=v2). Read the file COPYING that comes with GRASS
  17. for details.
  18. @author Soeren Gebbert
  19. """
  20. from core import *
  21. ###############################################################################
  22. class dict_sql_serializer(object):
  23. def __init__(self):
  24. self.D = {}
  25. def serialize(self, type, table, where=None):
  26. """Convert the internal dictionary into a string of semicolon separated SQL statements
  27. The keys are the colum names and the values are the row entries
  28. @type must be SELECT. INSERT, UPDATE
  29. @table The name of the table to select, insert or update
  30. @where The optinal where statment
  31. @return the sql string
  32. """
  33. sql = ""
  34. args = []
  35. # Create ordered select statement
  36. if type == "SELECT":
  37. sql += 'SELECT '
  38. count = 0
  39. for key in self.D.keys():
  40. if count == 0:
  41. sql += ' %s ' % key
  42. else:
  43. sql += ' , %s ' % key
  44. count += 1
  45. sql += ' FROM ' + table + ' '
  46. if where:
  47. sql += where
  48. # Create insert statement
  49. if type =="INSERT":
  50. count = 0
  51. sql += 'INSERT INTO ' + table + ' ('
  52. for key in self.D.keys():
  53. if count == 0:
  54. sql += ' %s ' % key
  55. else:
  56. sql += ' ,%s ' % key
  57. count += 1
  58. count = 0
  59. sql += ') VALUES ('
  60. for key in self.D.keys():
  61. if count == 0:
  62. if dbmi.paramstyle == "qmark":
  63. sql += '?'
  64. else:
  65. sql += '%s'
  66. else:
  67. if dbmi.paramstyle == "qmark":
  68. sql += ' ,?'
  69. else:
  70. sql += ' ,%s'
  71. count += 1
  72. args.append(self.D[key])
  73. sql += ') '
  74. if where:
  75. sql += where
  76. # Create update statement for existing entries
  77. if type =="UPDATE":
  78. count = 0
  79. sql += 'UPDATE ' + table + ' SET '
  80. for key in self.D.keys():
  81. # Update only entries which are not None
  82. if self.D[key] != None:
  83. if count == 0:
  84. if dbmi.paramstyle == "qmark":
  85. sql += ' %s = ? ' % key
  86. else:
  87. sql += ' %s ' % key
  88. sql += '= %s '
  89. else:
  90. if dbmi.paramstyle == "qmark":
  91. sql += ' ,%s = ? ' % key
  92. else:
  93. sql += ' ,%s ' % key
  94. sql += '= %s '
  95. count += 1
  96. args.append(self.D[key])
  97. if where:
  98. sql += where
  99. # Create update statement
  100. if type =="UPDATE ALL":
  101. count = 0
  102. sql += 'UPDATE ' + table + ' SET '
  103. for key in self.D.keys():
  104. if count == 0:
  105. if dbmi.paramstyle == "qmark":
  106. sql += ' %s = ? ' % key
  107. else:
  108. sql += ' %s ' % key
  109. sql += '= %s '
  110. else:
  111. if dbmi.paramstyle == "qmark":
  112. sql += ' ,%s = ? ' % key
  113. else:
  114. sql += ' ,%s ' % key
  115. sql += '= %s '
  116. count += 1
  117. args.append(self.D[key])
  118. if where:
  119. sql += where
  120. return sql, tuple(args)
  121. def deserialize(self, row):
  122. """Convert the content of the dbmi row into the internal dictionary"""
  123. self.D = {}
  124. for key in row.keys():
  125. self.D[key] = row[key]
  126. def clear(self):
  127. """Remove all the content of this class"""
  128. self.D = {}
  129. def print_self(self):
  130. print self.D
  131. def test(self):
  132. t = dict_sql_serializer()
  133. t.D["id"] = "soil@PERMANENT"
  134. t.D["name"] = "soil"
  135. t.D["mapset"] = "PERMANENT"
  136. t.D["creator"] = "soeren"
  137. t.D["creation_time"] = datetime.now()
  138. t.D["modification_time"] = datetime.now()
  139. t.D["revision"] = 1
  140. sql, values = t.serialize(type="SELECT", table="raster_base")
  141. print sql, '\n', values
  142. sql, values = t.serialize(type="INSERT", table="raster_base")
  143. print sql, '\n', values
  144. sql, values = t.serialize(type="UPDATE", table="raster_base")
  145. print sql, '\n', values
  146. ###############################################################################
  147. class sql_database_interface(dict_sql_serializer):
  148. """This is the sql database interface"""
  149. def __init__(self, table=None, ident=None, database=None):
  150. dict_sql_serializer.__init__(self)
  151. self.table = table # Name of the table, set in the subclass
  152. if database == None:
  153. self.database = get_grass_location_db_path()
  154. else:
  155. self.database = database
  156. self.ident = ident
  157. def get_table_name(self):
  158. return self.table
  159. def connect(self):
  160. #print "Connect to", self.database
  161. if dbmi.__name__ == "sqlite3":
  162. self.connection = dbmi.connect(self.database, detect_types=dbmi.PARSE_DECLTYPES|dbmi.PARSE_COLNAMES)
  163. self.connection.row_factory = dbmi.Row
  164. self.connection.isolation_level = None
  165. self.cursor = self.connection.cursor()
  166. elif dbmi.__name__ == "psycopg2":
  167. self.connection = dbmi.connect(self.database)
  168. self.connection.set_isolation_level(dbmi.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
  169. self.cursor = self.connection.cursor(cursor_factory=dbmi.extras.DictCursor)
  170. def close(self):
  171. #print "Close connection to", self.database
  172. self.connection.commit()
  173. self.cursor.close()
  174. def get_delete_statement(self):
  175. return "DELETE FROM " + self.get_table_name() + " WHERE id = \'" + str(self.ident) + "\'"
  176. def delete(self, dbif=None):
  177. sql = self.get_delete_statement()
  178. #print sql
  179. if dbif:
  180. dbif.cursor.execute(sql)
  181. else:
  182. self.connect()
  183. self.cursor.execute(sql)
  184. self.close()
  185. def get_is_in_db_statement(self):
  186. return "SELECT id FROM " + self.get_table_name() + " WHERE id = \'" + str(self.ident) + "\'"
  187. def is_in_db(self, dbif=None):
  188. sql = self.get_is_in_db_statement()
  189. #print sql
  190. if dbif:
  191. dbif.cursor.execute(sql)
  192. row = dbif.cursor.fetchone()
  193. else:
  194. self.connect()
  195. self.cursor.execute(sql)
  196. row = self.cursor.fetchone()
  197. self.close()
  198. # Nothing found
  199. if row == None:
  200. return False
  201. return True
  202. def get_select_statement(self):
  203. return self.serialize("SELECT", self.get_table_name(), "WHERE id = \'" + str(self.ident) + "\'")
  204. def select(self, dbif=None):
  205. sql, args = self.get_select_statement()
  206. #print sql
  207. #print args
  208. if dbif:
  209. if len(args) == 0:
  210. dbif.cursor.execute(sql)
  211. else:
  212. dbif.cursor.execute(sql, args)
  213. row = dbif.cursor.fetchone()
  214. else:
  215. self.connect()
  216. if len(args) == 0:
  217. self.cursor.execute(sql)
  218. else:
  219. self.cursor.execute(sql, args)
  220. row = self.cursor.fetchone()
  221. self.close()
  222. # Nothing found
  223. if row == None:
  224. return False
  225. if len(row) > 0:
  226. self.deserialize(row)
  227. else:
  228. raise IOError
  229. return True
  230. def get_insert_statement(self):
  231. return self.serialize("INSERT", self.get_table_name())
  232. def insert(self, dbif=None):
  233. sql, args = self.get_insert_statement()
  234. #print sql
  235. #print args
  236. if dbif:
  237. dbif.cursor.execute(sql, args)
  238. else:
  239. self.connect()
  240. self.cursor.execute(sql, args)
  241. self.close()
  242. def get_update_statement(self):
  243. return self.serialize("UPDATE", self.get_table_name(), "WHERE id = \'" + str(self.ident) + "\'")
  244. def update(self, dbif=None):
  245. if self.ident == None:
  246. raise IOError("Missing identifer");
  247. sql, args = self.get_update_statement()
  248. #print sql
  249. #print args
  250. if dbif:
  251. dbif.cursor.execute(sql, args)
  252. else:
  253. self.connect()
  254. self.cursor.execute(sql, args)
  255. self.close()
  256. def get_update_all_statement(self):
  257. return self.serialize("UPDATE ALL", self.get_table_name(), "WHERE id = \'" + str(self.ident) + "\'")
  258. def update_all(self, dbif=None):
  259. if self.ident == None:
  260. raise IOError("Missing identifer");
  261. sql, args = self.get_update_all_statement()
  262. #print sql
  263. #print args
  264. if dbif:
  265. dbif.cursor.execute(sql, args)
  266. else:
  267. self.connect()
  268. self.cursor.execute(sql, args)
  269. self.close()
  270. ###############################################################################
  271. class dataset_base(sql_database_interface):
  272. """This is the base class for all maps and spacetime datasets storing basic information"""
  273. def __init__(self, table=None, ident=None, name=None, mapset=None, creator=None, ctime=None,\
  274. mtime=None, ttype=None, revision=1):
  275. sql_database_interface.__init__(self, table, ident)
  276. self.set_id(ident)
  277. self.set_name(name)
  278. self.set_mapset(mapset)
  279. self.set_creator(creator)
  280. self.set_ctime(ctime)
  281. self.set_ttype(ttype)
  282. #self.set_mtime(mtime)
  283. #self.set_revision(revision)
  284. def set_id(self, ident):
  285. """Convenient method to set the unique identifier (primary key)"""
  286. self.ident = ident
  287. self.D["id"] = ident
  288. def set_name(self, name):
  289. """Set the name of the map"""
  290. self.D["name"] = name
  291. def set_mapset(self, mapset):
  292. """Set the mapset of the map"""
  293. self.D["mapset"] = mapset
  294. def set_creator(self, creator):
  295. """Set the creator of the map"""
  296. self.D["creator"] = creator
  297. def set_ctime(self, ctime=None):
  298. """Set the creation time of the map, if nothing set the current time is used"""
  299. if ctime == None:
  300. self.D["creation_time"] = datetime.now()
  301. else:
  302. self.D["creation_time"] = ctime
  303. def set_ttype(self, ttype):
  304. """Set the temporal type of the map: absolute or relative, if nothing set absolute time will assumed"""
  305. if ttype == None or (ttype != "absolute" and ttype != "relative"):
  306. self.D["temporal_type"] = "absolute"
  307. else:
  308. self.D["temporal_type"] = ttype
  309. # def set_mtime(self, mtime=None):
  310. # """Set the modification time of the map, if nothing set the current time is used"""
  311. # if mtime == None:
  312. # self.D["modification_time"] = datetime.now()
  313. # else:
  314. # self.D["modification_time"] = mtime
  315. # def set_revision(self, revision=1):
  316. # """Set the revision of the map: if nothing set revision 1 will assumed"""
  317. # self.D["revision"] = revision
  318. def get_id(self):
  319. """Convenient method to get the unique identifier (primary key)
  320. @return None if not found
  321. """
  322. if self.D.has_key("id"):
  323. return self.D["id"]
  324. else:
  325. return None
  326. def get_name(self):
  327. """Get the name of the map
  328. @return None if not found"""
  329. if self.D.has_key("name"):
  330. return self.D["name"]
  331. else:
  332. return None
  333. def get_mapset(self):
  334. """Get the mapset of the map
  335. @return None if not found"""
  336. if self.D.has_key("mapset"):
  337. return self.D["mapset"]
  338. else:
  339. return None
  340. def get_creator(self):
  341. """Get the creator of the map
  342. @return None if not found"""
  343. if self.D.has_key("creator"):
  344. return self.D["creator"]
  345. else:
  346. return None
  347. def get_ctime(self):
  348. """Get the creation time of the map, datatype is datetime
  349. @return None if not found"""
  350. if self.D.has_key("creation_time"):
  351. return self.D["creation_time"]
  352. else:
  353. return None
  354. def get_ttype(self):
  355. """Get the temporal type of the map
  356. @return None if not found"""
  357. if self.D.has_key("temporal_type"):
  358. return self.D["temporal_type"]
  359. else:
  360. return None
  361. # def get_mtime(self):
  362. # """Get the modification time of the map, datatype is datetime
  363. # @return None if not found"""
  364. # if self.D.has_key("modification_time"):
  365. # return self.D["modification_time"]
  366. # else:
  367. # return None
  368. # def get_revision(self):
  369. # """Get the revision of the map
  370. # @return None if not found"""
  371. # if self.D.has_key("revision"):
  372. # return self.D["revision"]
  373. # else:
  374. # return None
  375. def print_info(self):
  376. """Print information about this class in human readable style"""
  377. # 0123456789012345678901234567890
  378. print " +-------------------- Basic information -------------------------------------+"
  379. print " | Id: ........................ " + str(self.get_id())
  380. print " | Name: ...................... " + str(self.get_name())
  381. print " | Mapset: .................... " + str(self.get_mapset())
  382. print " | Creator: ................... " + str(self.get_creator())
  383. print " | Creation time: ............. " + str(self.get_ctime())
  384. # print " | Modification time: ......... " + str(self.get_mtime())
  385. print " | Temporal type: ............. " + str(self.get_ttype())
  386. # print " | Revision in database: ...... " + str(self.get_revision())
  387. def print_shell_info(self):
  388. """Print information about this class in shell style"""
  389. print "id=" + str(self.get_id())
  390. print "name=" + str(self.get_name())
  391. print "mapset=" + str(self.get_mapset())
  392. print "creator=" + str(self.get_creator())
  393. print "creation_time=" + str(self.get_ctime())
  394. # print "modification_time=" + str(self.get_mtime())
  395. print "temporal_type=" + str(self.get_ttype())
  396. # print "revision=" + str(self.get_revision())
  397. ###############################################################################
  398. class raster_base(dataset_base):
  399. def __init__(self, ident=None, name=None, mapset=None, creator=None, creation_time=None,\
  400. modification_time=None, temporal_type=None, revision=1):
  401. dataset_base.__init__(self, "raster_base", ident, name, mapset, creator, creation_time,\
  402. modification_time, temporal_type, revision)
  403. class raster3d_base(dataset_base):
  404. def __init__(self, ident=None, name=None, mapset=None, creator=None, creation_time=None,\
  405. modification_time=None, temporal_type=None, revision=1):
  406. dataset_base.__init__(self, "raster3d_base", ident, name, mapset, creator, creation_time,\
  407. modification_time, temporal_type, revision)
  408. class vector_base(dataset_base):
  409. def __init__(self, ident=None, name=None, mapset=None, creator=None, creation_time=None,\
  410. modification_time=None, temporal_type=None, revision=1):
  411. dataset_base.__init__(self, "vector_base", ident, name, mapset, creator, creation_time,\
  412. modification_time, temporal_type, revision)
  413. ###############################################################################
  414. class stds_base(dataset_base):
  415. def __init__(self, table=None, ident=None, name=None, mapset=None, semantic_type=None, creator=None, creation_time=None,\
  416. modification_time=None, temporal_type=None, revision=1):
  417. dataset_base.__init__(self, table, ident, name, mapset, creator, creation_time,\
  418. modification_time, temporal_type, revision)
  419. self.set_semantic_type(semantic_type)
  420. def set_semantic_type(self, semantic_type):
  421. """Set the semantic type of the space time dataset"""
  422. self.D["semantic_type"] = semantic_type
  423. def get_semantic_type(self):
  424. """Get the semantic type of the space time dataset
  425. @return None if not found"""
  426. if self.D.has_key("semantic_type"):
  427. return self.D["semantic_type"]
  428. else:
  429. return None
  430. ###############################################################################
  431. class strds_base(stds_base):
  432. def __init__(self, ident=None, name=None, mapset=None, semantic_type=None, creator=None, creation_time=None,\
  433. modification_time=None, temporal_type=None, revision=1):
  434. stds_base.__init__(self, "strds_base", ident, name, mapset, semantic_type, creator, creation_time,\
  435. modification_time, temporal_type, revision)
  436. class str3ds_base(stds_base):
  437. def __init__(self, ident=None, name=None, mapset=None, semantic_type=None, creator=None, creation_time=None,\
  438. modification_time=None, temporal_type=None, revision=1):
  439. stds_base.__init__(self, "str3ds_base", ident, name, mapset, semantic_type, creator, creation_time,\
  440. modification_time, temporal_type, revision)
  441. class stvds_base(stds_base):
  442. def __init__(self, ident=None, name=None, mapset=None, semantic_type=None, creator=None, creation_time=None,\
  443. modification_time=None, temporal_type=None, revision=1):
  444. stds_base.__init__(self, "stvds_base", ident, name, mapset, semantic_type, creator, creation_time,\
  445. modification_time, temporal_type, revision)