base.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. """!@package grass.temporal
  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 store basic information like id, name,
  6. mapset creation and modification time as well as sql serialization and de-serialization
  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 column 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 optional where statement
  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. sql += ";\n"
  49. # Create insert statement
  50. if type =="INSERT":
  51. count = 0
  52. sql += 'INSERT INTO ' + table + ' ('
  53. for key in self.D.keys():
  54. if count == 0:
  55. sql += ' %s ' % key
  56. else:
  57. sql += ' ,%s ' % key
  58. count += 1
  59. count = 0
  60. sql += ') VALUES ('
  61. for key in self.D.keys():
  62. if count == 0:
  63. if dbmi.paramstyle == "qmark":
  64. sql += '?'
  65. else:
  66. sql += '%s'
  67. else:
  68. if dbmi.paramstyle == "qmark":
  69. sql += ' ,?'
  70. else:
  71. sql += ' ,%s'
  72. count += 1
  73. args.append(self.D[key])
  74. sql += ') '
  75. if where:
  76. sql += where
  77. sql += ";\n"
  78. # Create update statement for existing entries
  79. if type =="UPDATE":
  80. count = 0
  81. sql += 'UPDATE ' + table + ' SET '
  82. for key in self.D.keys():
  83. # Update only entries which are not None
  84. if self.D[key] != None:
  85. if count == 0:
  86. if dbmi.paramstyle == "qmark":
  87. sql += ' %s = ? ' % key
  88. else:
  89. sql += ' %s ' % key
  90. sql += '= %s '
  91. else:
  92. if dbmi.paramstyle == "qmark":
  93. sql += ' ,%s = ? ' % key
  94. else:
  95. sql += ' ,%s ' % key
  96. sql += '= %s '
  97. count += 1
  98. args.append(self.D[key])
  99. if where:
  100. sql += where
  101. sql += ";\n"
  102. # Create update statement for all entries
  103. if type =="UPDATE ALL":
  104. count = 0
  105. sql += 'UPDATE ' + table + ' SET '
  106. for key in self.D.keys():
  107. if count == 0:
  108. if dbmi.paramstyle == "qmark":
  109. sql += ' %s = ? ' % key
  110. else:
  111. sql += ' %s ' % key
  112. sql += '= %s '
  113. else:
  114. if dbmi.paramstyle == "qmark":
  115. sql += ' ,%s = ? ' % key
  116. else:
  117. sql += ' ,%s ' % key
  118. sql += '= %s '
  119. count += 1
  120. args.append(self.D[key])
  121. if where:
  122. sql += where
  123. sql += ";\n"
  124. return sql, tuple(args)
  125. def deserialize(self, row):
  126. """!Convert the content of the dbmi dictionary like row into the internal dictionary
  127. @param row: The dictionary like row to store in the internal dict
  128. """
  129. self.D = {}
  130. for key in row.keys():
  131. self.D[key] = row[key]
  132. def clear(self):
  133. """!Initialize the internal storage"""
  134. self.D = {}
  135. def print_self(self):
  136. print self.D
  137. def test(self):
  138. t = dict_sql_serializer()
  139. t.D["id"] = "soil@PERMANENT"
  140. t.D["name"] = "soil"
  141. t.D["mapset"] = "PERMANENT"
  142. t.D["creator"] = "soeren"
  143. t.D["creation_time"] = datetime.now()
  144. t.D["modification_time"] = datetime.now()
  145. t.D["revision"] = 1
  146. sql, values = t.serialize(type="SELECT", table="raster_base")
  147. print sql, '\n', values
  148. sql, values = t.serialize(type="INSERT", table="raster_base")
  149. print sql, '\n', values
  150. sql, values = t.serialize(type="UPDATE", table="raster_base")
  151. print sql, '\n', values
  152. ###############################################################################
  153. class sql_database_interface(dict_sql_serializer):
  154. """!This class represents the SQL database interface
  155. Functions to insert, select and update the internal structure of this class
  156. in the temporal database are implemented. The following DBMS are supported:
  157. * sqlite via the sqlite3 standard library
  158. * postgresql via psycopg2
  159. This is the base class for raster, raster3d, vector and space time datasets
  160. data management classes:
  161. * Identification information (base)
  162. * Spatial extent
  163. * Temporal extent
  164. * Metadata
  165. """
  166. def __init__(self, table=None, ident=None):
  167. """!Constructor of this class
  168. @param table: The name of the table
  169. @param ident: The identifier (primary key) of this object in the database table
  170. """
  171. dict_sql_serializer.__init__(self)
  172. self.table = table # Name of the table, set in the subclass
  173. self.ident = ident
  174. def get_table_name(self):
  175. """!Return the name of the table in which the internal data are inserted, updated or selected"""
  176. return self.table
  177. def connect(self):
  178. """!Connect to the DBMI to execute SQL statements
  179. Supported backends are sqlite3 and postgresql
  180. """
  181. init = get_temporal_dbmi_init_string()
  182. #print "Connect to", self.database
  183. if dbmi.__name__ == "sqlite3":
  184. self.connection = dbmi.connect(init, detect_types=dbmi.PARSE_DECLTYPES|dbmi.PARSE_COLNAMES)
  185. self.connection.row_factory = dbmi.Row
  186. self.connection.isolation_level = None
  187. self.cursor = self.connection.cursor()
  188. self.cursor.execute("PRAGMA synchronous = OFF")
  189. self.cursor.execute("PRAGMA journal_mode = MEMORY")
  190. elif dbmi.__name__ == "psycopg2":
  191. self.connection = dbmi.connect(init)
  192. #self.connection.set_isolation_level(dbmi.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
  193. self.cursor = self.connection.cursor(cursor_factory=dbmi.extras.DictCursor)
  194. def close(self):
  195. """!Close the DBMI connection"""
  196. #print "Close connection to", self.database
  197. self.connection.commit()
  198. self.cursor.close()
  199. def _mogrify_sql_statement(self, content, dbif=None):
  200. """!Return the SQL statement and arguments as executable SQL string
  201. """
  202. sql = content[0]
  203. args = content[1]
  204. if dbmi.__name__ == "psycopg2":
  205. if len(args) == 0:
  206. return sql
  207. else:
  208. if dbif:
  209. try:
  210. return dbif.cursor.mogrify(sql, args)
  211. except:
  212. print sql, args
  213. raise
  214. else:
  215. self.connect()
  216. statement = self.cursor.mogrify(sql, args)
  217. self.close()
  218. return statement
  219. elif dbmi.__name__ == "sqlite3":
  220. if len(args) == 0:
  221. return sql
  222. else:
  223. # Unfortunately as sqlite does not support
  224. # the transformation of sql strings and qmarked or
  225. # named arguments we must make our hands dirty
  226. # and do it by ourself. :(
  227. # Doors are open for SQL injection because of the
  228. # limited python sqlite3 implementation!!!
  229. pos = 0
  230. count = 0
  231. maxcount = 100
  232. statement = sql
  233. while count < maxcount:
  234. pos = statement.find("?", pos + 1)
  235. if pos == -1:
  236. break
  237. if args[count] == None:
  238. statement = "%sNULL%s"%(statement[0:pos], statement[pos+1:])
  239. elif isinstance(args[count], (int, long)):
  240. statement = "%s%d%s"%(statement[0:pos], args[count],statement[pos+1:])
  241. elif isinstance(args[count], float):
  242. statement = "%s%f%s"%(statement[0:pos], args[count],statement[pos+1:])
  243. else:
  244. # Default is a string, this works for datetime objects too
  245. statement = "%s\'%s\'%s"%(statement[0:pos], str(args[count]),statement[pos+1:])
  246. count += 1
  247. return statement
  248. def get_delete_statement(self):
  249. """!Return the delete string"""
  250. return "DELETE FROM " + self.get_table_name() + " WHERE id = \'" + str(self.ident) + "\';\n"
  251. def delete(self, dbif=None):
  252. """!Delete the entry of this object from the temporal database"""
  253. sql = self.get_delete_statement()
  254. #print sql
  255. if dbif:
  256. dbif.cursor.execute(sql)
  257. else:
  258. self.connect()
  259. self.cursor.execute(sql)
  260. self.close()
  261. def get_is_in_db_statement(self):
  262. """Return the selection string"""
  263. return "SELECT id FROM " + self.get_table_name() + " WHERE id = \'" + str(self.ident) + "\';\n"
  264. def is_in_db(self, dbif=None):
  265. """!Check if this object is present in the temporal database
  266. @param dbif: The database interface to be used
  267. """
  268. sql = self.get_is_in_db_statement()
  269. #print sql
  270. if dbif:
  271. dbif.cursor.execute(sql)
  272. row = dbif.cursor.fetchone()
  273. else:
  274. self.connect()
  275. self.cursor.execute(sql)
  276. row = self.cursor.fetchone()
  277. self.close()
  278. # Nothing found
  279. if row == None:
  280. return False
  281. return True
  282. def get_select_statement(self):
  283. """!Return the sql statement and the argument list in database specific style"""
  284. return self.serialize("SELECT", self.get_table_name(), "WHERE id = \'" + str(self.ident) + "\'")
  285. def get_select_statement_mogrified(self, dbif=None):
  286. """!Return the select statement as mogrified string"""
  287. return self._mogrify_sql_statement(self.get_select_statement(), dbif)
  288. def select(self, dbif=None):
  289. """!Select the content from the temporal database and store it
  290. in the internal dictionary structure
  291. @param dbif: The database interface to be used
  292. """
  293. sql, args = self.get_select_statement()
  294. #print sql
  295. #print args
  296. if dbif:
  297. if len(args) == 0:
  298. dbif.cursor.execute(sql)
  299. else:
  300. dbif.cursor.execute(sql, args)
  301. row = dbif.cursor.fetchone()
  302. else:
  303. self.connect()
  304. if len(args) == 0:
  305. self.cursor.execute(sql)
  306. else:
  307. self.cursor.execute(sql, args)
  308. row = self.cursor.fetchone()
  309. self.close()
  310. # Nothing found
  311. if row == None:
  312. return False
  313. if len(row) > 0:
  314. self.deserialize(row)
  315. else:
  316. core.fatal(_("Object <%s> not found in the temporal database") % self.get_id())
  317. return True
  318. def get_insert_statement(self):
  319. """!Return the sql statement and the argument list in database specific style"""
  320. return self.serialize("INSERT", self.get_table_name())
  321. def get_insert_statement_mogrified(self, dbif=None):
  322. """!Return the insert statement as mogrified string"""
  323. return self._mogrify_sql_statement(self.get_insert_statement(), dbif)
  324. def insert(self, dbif=None):
  325. """!Serialize the content of this object and store it in the temporal
  326. database using the internal identifier
  327. @param dbif: The database interface to be used
  328. """
  329. sql, args = self.get_insert_statement()
  330. #print sql
  331. #print args
  332. if dbif:
  333. dbif.cursor.execute(sql, args)
  334. else:
  335. self.connect()
  336. self.cursor.execute(sql, args)
  337. self.close()
  338. def get_update_statement(self):
  339. """!Return the sql statement and the argument list in database specific style"""
  340. return self.serialize("UPDATE", self.get_table_name(), "WHERE id = \'" + str(self.ident) + "\'")
  341. def get_update_statement_mogrified(self,dbif=None):
  342. """!Return the update statement as mogrified string"""
  343. return self._mogrify_sql_statement(self.get_update_statement(), dbif)
  344. def update(self, dbif=None):
  345. """!Serialize the content of this object and update it in the temporal
  346. database using the internal identifier
  347. Only object entries which are exists (not None) are updated
  348. @param dbif: The database interface to be used
  349. """
  350. if self.ident == None:
  351. raise IOError("Missing identifer");
  352. sql, args = self.get_update_statement()
  353. #print sql
  354. #print args
  355. if dbif:
  356. dbif.cursor.execute(sql, args)
  357. else:
  358. self.connect()
  359. self.cursor.execute(sql, args)
  360. self.close()
  361. def get_update_all_statement(self):
  362. """!Return the sql statement and the argument list in database specific style"""
  363. return self.serialize("UPDATE ALL", self.get_table_name(), "WHERE id = \'" + str(self.ident) + "\'")
  364. def get_update_all_statement_mogrified(self, dbif=None):
  365. """!Return the update all statement as mogrified string"""
  366. return self._mogrify_sql_statement(self.get_update_all_statement(), dbif)
  367. def update_all(self, dbif=None):
  368. """!Serialize the content of this object, including None objects, and update it in the temporal
  369. database using the internal identifier
  370. @param dbif: The database interface to be used
  371. """
  372. if self.ident == None:
  373. raise IOError("Missing identifer");
  374. sql, args = self.get_update_all_statement()
  375. #print sql
  376. #print args
  377. if dbif:
  378. dbif.cursor.execute(sql, args)
  379. else:
  380. self.connect()
  381. self.cursor.execute(sql, args)
  382. self.close()
  383. ###############################################################################
  384. class dataset_base(sql_database_interface):
  385. """!This is the base class for all maps and spacetime datasets storing basic identification information"""
  386. def __init__(self, table=None, ident=None, name=None, mapset=None, creator=None, ctime=None,\
  387. mtime=None, ttype=None, revision=1):
  388. sql_database_interface.__init__(self, table, ident)
  389. self.set_id(ident)
  390. if ident != None and name == None and mapset == None:
  391. if ident.find("@") >= 0:
  392. name, mapset = ident.split("@")
  393. if name.find(":") >= 0:
  394. name, layer = ident.split(":")
  395. self.set_name(name)
  396. self.set_mapset(mapset)
  397. self.set_creator(creator)
  398. self.set_ctime(ctime)
  399. self.set_ttype(ttype)
  400. #self.set_mtime(mtime)
  401. #self.set_revision(revision)
  402. def set_id(self, ident):
  403. """!Convenient method to set the unique identifier (primary key)
  404. @param ident: The unique identifier should be a combination of the dataset name, layer name and the mapset name@mapset
  405. """
  406. self.ident = ident
  407. self.D["id"] = ident
  408. def set_name(self, name):
  409. """!Set the name of the dataset
  410. @param name: The name of the dataset
  411. """
  412. self.D["name"] = name
  413. def set_mapset(self, mapset):
  414. """!Set the mapset of the dataset
  415. @param mapsets: The name of the mapset in which this dataset is stored
  416. """
  417. self.D["mapset"] = mapset
  418. def set_layer(self, layer):
  419. """!Convenient method to set the layer of the map (part of primary key)
  420. Layer are currently supported for vector maps
  421. @param layer: The layer of the map
  422. """
  423. self.D["layer"] = layer
  424. def set_creator(self, creator):
  425. """!Set the creator of the dataset
  426. @param creator: The name of the creator
  427. """
  428. self.D["creator"] = creator
  429. def set_ctime(self, ctime=None):
  430. """!Set the creation time of the dataset, if nothing set the current time is used
  431. @param ctime: The current time of type datetime
  432. """
  433. if ctime == None:
  434. self.D["creation_time"] = datetime.now()
  435. else:
  436. self.D["creation_time"] = ctime
  437. def set_ttype(self, ttype):
  438. """!Set the temporal type of the dataset: absolute or relative, if nothing set absolute time will assumed
  439. @param ttype: The temporal type of the dataset "absolute or relative"
  440. """
  441. if ttype == None or (ttype != "absolute" and ttype != "relative"):
  442. self.D["temporal_type"] = "absolute"
  443. else:
  444. self.D["temporal_type"] = ttype
  445. # def set_mtime(self, mtime=None):
  446. # """!Set the modification time of the map, if nothing set the current time is used"""
  447. # if mtime == None:
  448. # self.D["modification_time"] = datetime.now()
  449. # else:
  450. # self.D["modification_time"] = mtime
  451. # def set_revision(self, revision=1):
  452. # """!Set the revision of the map: if nothing set revision 1 will assumed"""
  453. # self.D["revision"] = revision
  454. def get_id(self):
  455. """!Convenient method to get the unique identifier (primary key)
  456. @return None if not found
  457. """
  458. if self.D.has_key("id"):
  459. return self.D["id"]
  460. else:
  461. return None
  462. def get_map_id(self):
  463. """!Convenient method to get the unique map identifier without layer information
  464. @param return the name of the vector map as name@mapset
  465. """
  466. id = self.get_id()
  467. if id.find(":") >= 0:
  468. # Remove the layer identifier from the id
  469. return id.split("@")[0].split(":")[0] + "@" + id.split("@")[1]
  470. else:
  471. return id
  472. def get_layer(self):
  473. """!Convenient method to get the layer of the map (part of primary key)
  474. Layer are currently supported for vector maps
  475. @return None if not found
  476. """
  477. if self.D.has_key("layer"):
  478. return self.D["layer"]
  479. else:
  480. return None
  481. def get_name(self):
  482. """!Get the name of the dataset
  483. @return None if not found"""
  484. if self.D.has_key("name"):
  485. return self.D["name"]
  486. else:
  487. return None
  488. def get_mapset(self):
  489. """!Get the name of mapset of this dataset
  490. @return None if not found"""
  491. if self.D.has_key("mapset"):
  492. return self.D["mapset"]
  493. else:
  494. return None
  495. def get_creator(self):
  496. """!Get the creator of the dataset
  497. @return None if not found"""
  498. if self.D.has_key("creator"):
  499. return self.D["creator"]
  500. else:
  501. return None
  502. def get_ctime(self):
  503. """!Get the creation time of the dataset, datatype is datetime
  504. @return None if not found"""
  505. if self.D.has_key("creation_time"):
  506. return self.D["creation_time"]
  507. else:
  508. return None
  509. def get_ttype(self):
  510. """!Get the temporal type of the map
  511. @return None if not found"""
  512. if self.D.has_key("temporal_type"):
  513. return self.D["temporal_type"]
  514. else:
  515. return None
  516. # def get_mtime(self):
  517. # """!Get the modification time of the map, datatype is datetime
  518. # @return None if not found"""
  519. # if self.D.has_key("modification_time"):
  520. # return self.D["modification_time"]
  521. # else:
  522. # return None
  523. # def get_revision(self):
  524. # """!Get the revision of the map
  525. # @return None if not found"""
  526. # if self.D.has_key("revision"):
  527. # return self.D["revision"]
  528. # else:
  529. # return None
  530. def print_info(self):
  531. """!Print information about this class in human readable style"""
  532. # 0123456789012345678901234567890
  533. print " +-------------------- Basic information -------------------------------------+"
  534. print " | Id: ........................ " + str(self.get_id())
  535. print " | Name: ...................... " + str(self.get_name())
  536. print " | Mapset: .................... " + str(self.get_mapset())
  537. if self.get_layer():
  538. print " | Layer:...................... " + str(self.get_layer())
  539. print " | Creator: ................... " + str(self.get_creator())
  540. print " | Creation time: ............. " + str(self.get_ctime())
  541. # print " | Modification time: ......... " + str(self.get_mtime())
  542. print " | Temporal type: ............. " + str(self.get_ttype())
  543. # print " | Revision in database: ...... " + str(self.get_revision())
  544. def print_shell_info(self):
  545. """!Print information about this class in shell style"""
  546. print "id=" + str(self.get_id())
  547. print "name=" + str(self.get_name())
  548. print "mapset=" + str(self.get_mapset())
  549. if self.get_layer():
  550. print "layer=" + str(self.get_layer())
  551. print "creator=" + str(self.get_creator())
  552. print "creation_time=" + str(self.get_ctime())
  553. # print "modification_time=" + str(self.get_mtime())
  554. print "temporal_type=" + str(self.get_ttype())
  555. # print "revision=" + str(self.get_revision())
  556. ###############################################################################
  557. class raster_base(dataset_base):
  558. def __init__(self, ident=None, name=None, mapset=None, creator=None, creation_time=None,\
  559. modification_time=None, temporal_type=None, revision=1):
  560. dataset_base.__init__(self, "raster_base", ident, name, mapset, creator, creation_time,\
  561. modification_time, temporal_type, revision)
  562. class raster3d_base(dataset_base):
  563. def __init__(self, ident=None, name=None, mapset=None, creator=None, creation_time=None,\
  564. modification_time=None, temporal_type=None, revision=1):
  565. dataset_base.__init__(self, "raster3d_base", ident, name, mapset, creator, creation_time,\
  566. modification_time, temporal_type, revision)
  567. class vector_base(dataset_base):
  568. def __init__(self, ident=None, name=None, mapset=None, layer=None, creator=None, creation_time=None,\
  569. modification_time=None, temporal_type=None, revision=1):
  570. dataset_base.__init__(self, "vector_base", ident, name, mapset, creator, creation_time,\
  571. modification_time, temporal_type, revision)
  572. self.set_id(ident)
  573. if ident != None and name == None and mapset == None:
  574. if ident.find("@") >= 0:
  575. name, mapset = ident.split("@")
  576. if layer == None:
  577. if name.find(":") >= 0:
  578. name, layer = name.split(":")
  579. self.set_name(name)
  580. self.set_mapset(mapset)
  581. # Layer currently only in use by vector maps
  582. self.set_layer(layer)
  583. ###############################################################################
  584. class stds_base(dataset_base):
  585. def __init__(self, table=None, ident=None, name=None, mapset=None, semantic_type=None, creator=None, creation_time=None,\
  586. modification_time=None, temporal_type=None, revision=1):
  587. dataset_base.__init__(self, table, ident, name, mapset, creator, creation_time,\
  588. modification_time, temporal_type, revision)
  589. self.set_semantic_type(semantic_type)
  590. def set_semantic_type(self, semantic_type):
  591. """!Set the semantic type of the space time dataset"""
  592. self.D["semantic_type"] = semantic_type
  593. def get_semantic_type(self):
  594. """!Get the semantic type of the space time dataset
  595. @return None if not found"""
  596. if self.D.has_key("semantic_type"):
  597. return self.D["semantic_type"]
  598. else:
  599. return None
  600. def print_info(self):
  601. """!Print information about this class in human readable style"""
  602. dataset_base.print_info(self)
  603. # 0123456789012345678901234567890
  604. print " | Semantic type:.............. " + str(self.get_semantic_type())
  605. def print_shell_info(self):
  606. """!Print information about this class in shell style"""
  607. dataset_base.print_shell_info(self)
  608. print "semantic_type=" + str(self.get_semantic_type())
  609. ###############################################################################
  610. class strds_base(stds_base):
  611. def __init__(self, ident=None, name=None, mapset=None, semantic_type=None, creator=None, creation_time=None,\
  612. modification_time=None, temporal_type=None, revision=1):
  613. stds_base.__init__(self, "strds_base", ident, name, mapset, semantic_type, creator, creation_time,\
  614. modification_time, temporal_type, revision)
  615. class str3ds_base(stds_base):
  616. def __init__(self, ident=None, name=None, mapset=None, semantic_type=None, creator=None, creation_time=None,\
  617. modification_time=None, temporal_type=None, revision=1):
  618. stds_base.__init__(self, "str3ds_base", ident, name, mapset, semantic_type, creator, creation_time,\
  619. modification_time, temporal_type, revision)
  620. class stvds_base(stds_base):
  621. def __init__(self, ident=None, name=None, mapset=None, semantic_type=None, creator=None, creation_time=None,\
  622. modification_time=None, temporal_type=None, revision=1):
  623. stds_base.__init__(self, "stvds_base", ident, name, mapset, semantic_type, creator, creation_time,\
  624. modification_time, temporal_type, revision)
  625. ###############################################################################
  626. def init_dbif(dbif):
  627. """!This method checks if the database interface exists, if not a new one
  628. will be created and True will be returned
  629. Usage code sample:
  630. dbif, connect = self._init_dbif(dbif)
  631. if connect:
  632. dbif.close()
  633. """
  634. if dbif == None:
  635. dbif = sql_database_interface()
  636. dbif.connect()
  637. return dbif, True
  638. return dbif, False
  639. ###############################################################################
  640. def execute_transaction(statement, dbif=None):
  641. """!Execute a transactional SQL statement
  642. The BEGIN and END TRANSACTION statements will be added automatically
  643. to the sql statement
  644. @param statement The executable SQL statement or SQL script
  645. @param dbif The database interface, if None a new db interface will be created temporary
  646. """
  647. dbif, connect = init_dbif(dbif)
  648. sql_script = ""
  649. sql_script += "BEGIN TRANSACTION;\n"
  650. sql_script += statement
  651. sql_script += "END TRANSACTION;"
  652. try:
  653. if dbmi.__name__ == "sqlite3":
  654. dbif.cursor.executescript(statement)
  655. else:
  656. dbif.cursor.execute(statement)
  657. dbif.connection.commit()
  658. except:
  659. if connect == True:
  660. dbif.close()
  661. core.error(_("Unable to execute transaction:\n %s") % (statement))
  662. raise
  663. if connect:
  664. dbif.close()