mviews.php 14 KB

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