mviews.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <?php
  2. /**
  3. * @defgroup tripal_mviews_api Core Module Materalized Views API
  4. * @{
  5. * Provides an application programming interface (API) to manage materialized views in Chado.
  6. * The Perl-based chado comes with an interface for managing materialzed views. This
  7. * API provides an alternative Drupal-based method.
  8. * @}
  9. * @ingroup tripal_api
  10. */
  11. /**
  12. * Add a materialized view to the chado database to help speed data access.
  13. *
  14. * @param $name
  15. * The name of the materialized view.
  16. * @param $modulename
  17. * The name of the module submitting the materialized view (e.g. 'tripal_library')
  18. * @param $mv_table
  19. * The name of the table to add to chado. This is the table that can be queried.
  20. * @param $mv_specs
  21. * The table definition
  22. * @param $indexed
  23. * The columns that are to be indexed
  24. * @param $query
  25. * The SQL query that loads the materialized view with data
  26. * @param $special_index
  27. * function
  28. *
  29. * @ingroup tripal_mviews_api
  30. */
  31. function tripal_add_mview ($name,$modulename,$mv_table,$mv_specs,$indexed,$query,$special_index){
  32. $record = new stdClass();
  33. $record->name = $name;
  34. $record->modulename = $modulename;
  35. $record->mv_schema = 'DUMMY';
  36. $record->mv_table = $mv_table;
  37. $record->mv_specs = $mv_specs;
  38. $record->indexed = $indexed;
  39. $record->query = $query;
  40. $record->special_index = $special_index;
  41. // add the record to the tripal_mviews table and if successful
  42. // create the new materialized view in the chado schema
  43. if(drupal_write_record('tripal_mviews',$record)){
  44. // drop the table from chado if it exists
  45. $previous_db = tripal_db_set_active('chado'); // use chado database
  46. if (db_table_exists($mv_table)) {
  47. $sql = "DROP TABLE $mv_table";
  48. db_query($sql);
  49. }
  50. tripal_db_set_active($previous_db); // now use drupal database
  51. // now add the table for this view
  52. $index = '';
  53. if($indexed){
  54. $index = ", CONSTRAINT ". $mv_table . "_index UNIQUE ($indexed) ";
  55. }
  56. $sql = "CREATE TABLE {$mv_table} ($mv_specs $index)";
  57. $previous_db = tripal_db_set_active('chado'); // use chado database
  58. $results = db_query($sql);
  59. tripal_db_set_active($previous_db); // now use drupal database
  60. if($results){
  61. drupal_set_message(t("View '$name' created"));
  62. } else {
  63. // if we failed to create the view in chado then
  64. // remove the record from the tripal_jobs table
  65. $sql = "DELETE FROM {tripal_mviews} ".
  66. "WHERE mview_id = $record->mview_id";
  67. db_query($sql);
  68. }
  69. }
  70. }
  71. /**
  72. * Retrieve the materialized view_id given the name
  73. *
  74. * @param $view_name
  75. * The name of the materialized view
  76. *
  77. * @return
  78. * The unique identifier for the given view
  79. *
  80. * @ingroup tripal_mviews_api
  81. */
  82. function tripal_mviews_get_mview_id ($view_name){
  83. $sql = "SELECT * FROM {tripal_mviews} ".
  84. "WHERE name = '%s'";
  85. if(db_table_exists('tripal_mviews')){
  86. $mview = db_fetch_object(db_query($sql,$view_name));
  87. if($mview){
  88. return $mview->mview_id;
  89. }
  90. }
  91. return 0;
  92. }
  93. /**
  94. *
  95. *
  96. * @ingroup tripal_core
  97. */
  98. function tripal_mviews_action ($op,$mview_id){
  99. global $user;
  100. $args = array("$mview_id");
  101. if(!$mview_id){
  102. return '';
  103. }
  104. // get this mview details
  105. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = $mview_id ";
  106. $mview = db_fetch_object(db_query($sql));
  107. // add a job or perform the action based on the given operation
  108. if($op == 'update'){
  109. tripal_add_job("Update materialized view '$mview->name'",'tripal_core',
  110. 'tripal_update_mview',$args,$user->uid);
  111. }
  112. if($op == 'delete'){
  113. // remove the mview from the tripal_mviews table
  114. $sql = "DELETE FROM {tripal_mviews} ".
  115. "WHERE mview_id = $mview_id";
  116. db_query($sql);
  117. // drop the table from chado if it exists
  118. $previous_db = tripal_db_set_active('chado'); // use chado database
  119. if (db_table_exists($mview->mv_table)) {
  120. $sql = "DROP TABLE $mview->mv_table";
  121. db_query($sql);
  122. }
  123. tripal_db_set_active($previous_db); // now use drupal database
  124. }
  125. drupal_goto("admin/tripal/views/mviews");
  126. }
  127. /**
  128. * Update a Materialized View
  129. *
  130. * @param $mview_id
  131. * The unique identifier for the materialized view to be updated
  132. *
  133. * @return
  134. * True if successful, false otherwise
  135. *
  136. * @ingroup tripal_mviews_api
  137. */
  138. function tripal_update_mview ($mview_id){
  139. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = %d ";
  140. $mview = db_fetch_object(db_query($sql,$mview_id));
  141. if($mview){
  142. $previous_db = tripal_db_set_active('chado'); // use chado database
  143. $results = db_query("DELETE FROM {$mview->mv_table}");
  144. $results = db_query("INSERT INTO $mview->mv_table ($mview->query)");
  145. tripal_db_set_active($previous_db); // now use drupal database
  146. if($results){
  147. $record = new stdClass();
  148. $record->mview_id = $mview_id;
  149. $record->last_update = time();
  150. drupal_write_record('tripal_mviews',$record,'mview_id');
  151. return 1;
  152. } else {
  153. // TODO -- error handling
  154. return 0;
  155. }
  156. }
  157. }
  158. /**
  159. *
  160. *
  161. * @ingroup tripal_mviews_api
  162. */
  163. function tripal_mview_report ($mview_id) {
  164. // get this mview details
  165. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = $mview_id ";
  166. $mview = db_fetch_object(db_query($sql));
  167. // create a table with each row containig stats for
  168. // an individual job in the results set.
  169. $return_url = url("admin/tripal/views/mviews/");
  170. $output .= "<p><a href=\"$return_url\">Return to table of materialized views.</a></p>";
  171. $output .= "<br />";
  172. $output .= "<p>Details for <b>$mview->name</b>:</p>";
  173. $output .= "<br />";
  174. $output .= "<table class=\"border-table\">";
  175. if($mview->name){
  176. $output .= " <tr>".
  177. " <th>View Name</th>".
  178. " <td>$mview->name</td>".
  179. " </tr>";
  180. }
  181. if($mview->modulename){
  182. $output .= " <tr>".
  183. " <th>Module Name</th>".
  184. " <td>$mview->modulename</td>".
  185. " </tr>";
  186. }
  187. if($mview->mv_table){
  188. $output .= " <tr>".
  189. " <th>Table Name</th>".
  190. " <td>$mview->mv_table</td>".
  191. " </tr>";
  192. }
  193. if($mview->mv_specs){
  194. $output .= " <tr>".
  195. " <th>Table Field Definitions</th>".
  196. " <td>$mview->mv_specs</td>".
  197. " </tr>";
  198. }
  199. if($mview->query){
  200. $output .= " <tr>".
  201. " <th>Query</th>".
  202. " <td><pre>$mview->query</pre></td>".
  203. " </tr>";
  204. }
  205. if($mview->indexed){
  206. $output .= " <tr>".
  207. " <th>Indexed Fields</th>".
  208. " <td>$mview->indexed</td>".
  209. " </tr>";
  210. }
  211. if($mview->special_index){
  212. $output .= " <tr>".
  213. " <th>Special Indexed Fields</th>".
  214. " <td>$mview->speical_index</td>".
  215. " </tr>";
  216. }
  217. if($mview->last_update > 0){
  218. $update = format_date($mview->last_update);
  219. } else {
  220. $update = 'Not yet populated';
  221. }
  222. $output .= " <tr>".
  223. " <th>Last Update</th>".
  224. " <td>$update</td>".
  225. " </tr>";
  226. // build the URLs using the url function so we can handle installations where
  227. // clean URLs are or are not used
  228. $update_url = url("admin/tripal/views/mviews/action/update/$mview->mview_id");
  229. $delete_url = url("admin/tripal/views/mviews/action/delete/$mview->mview_id");
  230. $edit_url = url("admin/tripal/views/mviews/edit/$mview->mview_id");
  231. $output .= "<tr><th>Actions</th>".
  232. "<td> <a href='$update_url'>Update</a>, ".
  233. " <a href='$edit_url'>Edit</a>, ".
  234. " <a href='$delete_url'>Delete</a></td></tr>";
  235. $output .= "</table>";
  236. return $output;
  237. }
  238. /**
  239. *
  240. *
  241. * @ingroup tripal_mviews_api
  242. */
  243. function tripal_mviews_report () {
  244. $header = array('','MView Name','Last Update','');
  245. $rows = array();
  246. $mviews = db_query("SELECT * FROM {tripal_mviews} ORDER BY name");
  247. while($mview = db_fetch_object($mviews)){
  248. if($mview->last_update > 0){
  249. $update = format_date($mview->last_update);
  250. } else {
  251. $update = 'Not yet populated';
  252. }
  253. $rows[] = array(
  254. l('View',"admin/tripal/views/mviews/report/$mview->mview_id") ." | ".
  255. l('Update',"admin/tripal/views/mviews/action/update/$mview->mview_id"),
  256. $mview->name,
  257. $update,
  258. l('Delete',"admin/tripal/views/mviews/action/delete/$mview->mview_id"),
  259. );
  260. }
  261. $rows[] = array(
  262. 'data' => array(
  263. array('data' => l('Create a new materialized view.',"admin/tripal/views/mviews/new"),
  264. 'colspan' => 4),
  265. )
  266. );
  267. return theme('table', $header, $rows);
  268. }
  269. /**
  270. *
  271. *
  272. * @ingroup tripal_core
  273. */
  274. function tripal_mviews_form(&$form_state = NULL,$mview_id = NULL){
  275. if(!$mview_id){
  276. $action = 'Add';
  277. } else {
  278. $action = 'Update';
  279. }
  280. // get this requested view
  281. if(strcmp($action,'Update')==0){
  282. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = $mview_id ";
  283. $mview = db_fetch_object(db_query($sql));
  284. # set the default values. If there is a value set in the
  285. # form_state then let's use that, otherwise, we'll pull
  286. # the values from the database
  287. $default_name = $form_state['values']['name'];
  288. $default_mv_table = $form_state['values']['mv_table'];
  289. $default_mv_specs = $form_state['values']['mv_specs'];
  290. $default_indexed = $form_state['values']['indexed'];
  291. $default_mvquery = $form_state['values']['mvquery'];
  292. $default_special_index = $form_state['values']['special_index'];
  293. if(!$default_name){
  294. $default_name = $mview->name;
  295. }
  296. if(!$default_mv_table){
  297. $default_mv_table = $mview->mv_table;
  298. }
  299. if(!$default_mv_specs){
  300. $default_mv_specs = $mview->mv_specs;
  301. }
  302. if(!$default_indexed){
  303. $default_indexed = $mview->indexed;
  304. }
  305. if(!$default_mvquery){
  306. $default_mvquery = $mview->query;
  307. }
  308. if(!$default_special_index){
  309. $default_special_index = $mview->special_index;
  310. }
  311. }
  312. // Build the form
  313. $form['action'] = array(
  314. '#type' => 'value',
  315. '#value' => $action
  316. );
  317. $form['mview_id'] = array(
  318. '#type' => 'value',
  319. '#value' => $mview_id
  320. );
  321. $form['name']= array(
  322. '#type' => 'textfield',
  323. '#title' => t('View Name'),
  324. '#description' => t('Please enter the name for this materialized view.'),
  325. '#required' => TRUE,
  326. '#default_value' => $default_name,
  327. '#weight' => 1
  328. );
  329. $form['mv_table']= array(
  330. '#type' => 'textfield',
  331. '#title' => t('Table Name'),
  332. '#description' => t('Please enter the Postgres table name that this view will generate in the database. You can use the schema and table name for querying the view'),
  333. '#required' => TRUE,
  334. '#default_value' => $default_mv_table,
  335. '#weight' => 3
  336. );
  337. $form['mv_specs']= array(
  338. '#type' => 'textarea',
  339. '#title' => t('Table Definition'),
  340. '#description' => t('Please enter the field definitions for this view. Each field should be separated by a comma or enter each field definition on each line.'),
  341. '#required' => TRUE,
  342. '#default_value' => $default_mv_specs,
  343. '#weight' => 4
  344. );
  345. $form['indexed']= array(
  346. '#type' => 'textarea',
  347. '#title' => t('Indexed Fields'),
  348. '#description' => t('Please enter the field names (as provided in the table definition above) that will be indexed for this view. Separate by a comma or enter each field on a new line.'),
  349. '#required' => FALSE,
  350. '#default_value' => $default_indexed,
  351. '#weight' => 5
  352. );
  353. $form['mvquery']= array(
  354. '#type' => 'textarea',
  355. '#title' => t('Query'),
  356. '#description' => t('Please enter the SQL statement used to populate the table.'),
  357. '#required' => TRUE,
  358. '#default_value' => $default_mvquery,
  359. '#weight' => 6
  360. );
  361. /**
  362. $form['special_index']= array(
  363. '#type' => 'textarea',
  364. '#title' => t('View Name'),
  365. '#description' => t('Please enter the name for this materialized view.'),
  366. '#required' => TRUE,
  367. '#default_value' => $default_special_index,
  368. '#weight' => 7
  369. );
  370. */
  371. $form['submit'] = array (
  372. '#type' => 'submit',
  373. '#value' => t($action),
  374. '#weight' => 8,
  375. '#executes_submit_callback' => TRUE,
  376. );
  377. $form['#redirect'] = 'admin/tripal/views/mviews';
  378. return $form;
  379. }
  380. /**
  381. *
  382. *
  383. * @ingroup tripal_core
  384. */
  385. function tripal_mviews_form_submit($form, &$form_state){
  386. $action = $form_state['values']['action'];
  387. if(strcmp($action,'Update')==0){
  388. $record = new stdClass();
  389. $record->mview_id = $form_state['values']['mview_id'];
  390. $record->name = $form_state['values']['name'];
  391. $record->mv_table = $form_state['values']['mv_table'];
  392. $record->mv_specs = $form_state['values']['mv_specs'];
  393. $record->indexed = $form_state['values']['indexed'];
  394. $record->query = $form_state['values']['mvquery'];
  395. $record->special_index = $form_state['values']['special_index'];
  396. // add the record to the tripal_mviews table and if successful
  397. // create the new materialized view in the chado schema
  398. if(drupal_write_record('tripal_mviews',$record,'mview_id')){
  399. drupal_set_message('View updated successfullly');
  400. } else {
  401. drupal_set_message('View update failed');
  402. }
  403. }
  404. else if(strcmp($action,'Add')==0){
  405. tripal_add_mview ($form_state['values']['name'], 'tripal_core',
  406. $form_state['values']['mv_table'], $form_state['values']['mv_specs'],
  407. $form_state['values']['indexed'], $form_state['values']['mvquery'],
  408. $form_state['values']['special_index']);
  409. }
  410. else {
  411. drupal_set_message("No action performed.");
  412. }
  413. return '';
  414. }