mviews.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. <?php
  2. /**
  3. * @file
  4. * Contains functions for the Materialized Views API
  5. * @defgroup tripal_mviews_api Core Module Materalized Views API
  6. * @{
  7. * Provides an application programming interface (API) to manage materialized views in Chado.
  8. * The Perl-based chado comes with an interface for managing materialzed views. This
  9. * API provides an alternative Drupal-based method.
  10. * @}
  11. * @ingroup tripal_api
  12. */
  13. /**
  14. * Add a materialized view to the chado database to help speed data access. This
  15. * function supports the older style where postgres column specifications
  16. * are provided using the $mv_table, $mv_specs and $indexed variables. It also
  17. * supports the newer preferred method where the materialized view is described
  18. * using the Drupal Schema API array.
  19. *
  20. * @param $name
  21. * The name of the materialized view.
  22. * @param $modulename
  23. * The name of the module submitting the materialized view (e.g. 'tripal_library')
  24. * @param $mv_table
  25. * The name of the table to add to chado. This is the table that can be queried.
  26. * @param $mv_specs
  27. * The table definition
  28. * @param $indexed
  29. * The columns that are to be indexed
  30. * @param $query
  31. * The SQL query that loads the materialized view with data
  32. * @param $special_index
  33. * currently not used
  34. * @param $comment
  35. * A string containing a description of the materialized view
  36. * @param $mv_schema
  37. * If using the newer Schema API array to define the materialized view then
  38. * this variable should contain the array or a string representation of the
  39. * array.
  40. *
  41. * @ingroup tripal_mviews_api
  42. */
  43. function tripal_add_mview($name, $modulename, $mv_table, $mv_specs, $indexed,
  44. $query, $special_index, $comment = NULL, $mv_schema = NULL) {
  45. // get the table name from the schema array
  46. $schema_arr = array();
  47. if ($mv_schema) {
  48. // if the schema is provided as a string then convert it to an array
  49. if (!is_array($mv_schema)) {
  50. eval("\$schema_arr = $mv_schema;");
  51. }
  52. // if the schema is provided as an array then create a string
  53. // copy of it for storage in the mview
  54. else {
  55. $schema_arr = $mv_schema;
  56. $mv_schema = var_export($schema_arr, 1);
  57. }
  58. $mv_table = $schema_arr['table'];
  59. }
  60. // Create a new record
  61. $record = new stdClass();
  62. $record->name = $name;
  63. $record->modulename = $modulename;
  64. $record->mv_table = $mv_table;
  65. $record->mv_specs = $mv_specs;
  66. $record->indexed = $indexed;
  67. $record->query = $query;
  68. $record->special_index = $special_index;
  69. $record->comment = $comment;
  70. $record->mv_schema = $mv_schema;
  71. // add the record to the tripal_mviews table and if successful
  72. // create the new materialized view in the chado schema
  73. if (drupal_write_record('tripal_mviews', $record)) {
  74. // drop the table from chado if it exists
  75. $previous_db = tripal_db_set_active('chado'); // use chado database
  76. if (db_table_exists($mv_table)) {
  77. $sql = "DROP TABLE $mv_table";
  78. db_query($sql);
  79. }
  80. tripal_db_set_active($previous_db); // now use drupal database
  81. // now construct the indexes
  82. $index = '';
  83. if ($indexed) {
  84. // add to the array of values
  85. $vals = preg_split("/[\n,]+/", $indexed);
  86. $index = '';
  87. foreach ($vals as $field) {
  88. $field = trim($field);
  89. $index .= "CREATE INDEX idx_${mv_table}_${field} ON $mv_table ($field);";
  90. }
  91. }
  92. // create the table differently depending on if it the traditional method
  93. // or the Drupal Schema API method
  94. if ($mv_schema) {
  95. if (!tripal_core_create_custom_table ($ret, $mv_table, $schema_arr, 0)) {
  96. drupal_set_message(t("Could not create the materialized view. Check Drupal error report logs."), 'error');
  97. }
  98. else {
  99. drupal_set_message(t("View '%name' created", array('%name' => $name)));
  100. }
  101. }
  102. else {
  103. // add the table to the database
  104. $sql = "CREATE TABLE {$mv_table} ($mv_specs); $index";
  105. $previous_db = tripal_db_set_active('chado'); // use chado database
  106. $results = db_query($sql);
  107. tripal_db_set_active($previous_db); // now use drupal database
  108. if ($results) {
  109. drupal_set_message(t("View '%name' created", array('%name' => $name)));
  110. }
  111. else {
  112. drupal_set_message(t("Failed to create the materialized view table: '%mv_table'", array('%mv_table' => $mv_table)), 'error');
  113. }
  114. }
  115. }
  116. }
  117. /**
  118. * Edits a materialized view to the chado database to help speed data access.This
  119. * function supports the older style where postgres column specifications
  120. * are provided using the $mv_table, $mv_specs and $indexed variables. It also
  121. * supports the newer preferred method where the materialized view is described
  122. * using the Drupal Schema API array.
  123. *
  124. * @param $mview_id
  125. * The mview_id of the materialized view to edit
  126. * @param $name
  127. * The name of the materialized view.
  128. * @param $modulename
  129. * The name of the module submitting the materialized view (e.g. 'tripal_library')
  130. * @param $mv_table
  131. * The name of the table to add to chado. This is the table that can be queried.
  132. * @param $mv_specs
  133. * The table definition
  134. * @param $indexed
  135. * The columns that are to be indexed
  136. * @param $query
  137. * The SQL query that loads the materialized view with data
  138. * @param $special_index
  139. * currently not used
  140. * @param $comment
  141. * A string containing a description of the materialized view
  142. * @param $mv_schema
  143. * If using the newer Schema API array to define the materialized view then
  144. * this variable should contain the array.
  145. *
  146. * @ingroup tripal_mviews_api
  147. */
  148. function tripal_edit_mview($mview_id, $name, $modulename, $mv_table, $mv_specs,
  149. $indexed, $query, $special_index, $comment = NULL, $mv_schema = NULL) {
  150. // get the table name from the schema array
  151. $schema_arr = array();
  152. if ($mv_schema) {
  153. // get the schema from the mv_specs and use it to add the custom table
  154. eval("\$schema_arr = $mv_schema;");
  155. $mv_table = $schema_arr['table'];
  156. }
  157. // Create a new record
  158. $record = new stdClass();
  159. $record->mview_id = $mview_id;
  160. $record->name = $name;
  161. $record->modulename = $modulename;
  162. $record->mv_schema = $mv_schema;
  163. $record->mv_table = $mv_table;
  164. $record->mv_specs = $mv_specs;
  165. $record->indexed = $indexed;
  166. $record->query = $query;
  167. $record->special_index = $special_index;
  168. $record->last_update = 0;
  169. $record->status = '';
  170. $record->comment = $comment;
  171. // drop the table from chado if it exists
  172. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = %d";
  173. $mview = db_fetch_object(db_query($sql, $mview_id));
  174. $previous_db = tripal_db_set_active('chado'); // use chado database
  175. if (db_table_exists($mview->mv_table)) {
  176. $sql = "DROP TABLE %s";
  177. db_query($sql, $mview->mv_table);
  178. }
  179. tripal_db_set_active($previous_db); // now use drupal database
  180. // update the record to the tripal_mviews table and if successful
  181. // create the new materialized view in the chado schema
  182. if (drupal_write_record('tripal_mviews', $record, 'mview_id')) {
  183. // drop the table from chado if it exists
  184. $previous_db = tripal_db_set_active('chado'); // use chado database
  185. if (db_table_exists($mv_table)) {
  186. $sql = "DROP TABLE %s";
  187. db_query($sql, $mv_table);
  188. }
  189. tripal_db_set_active($previous_db); // now use drupal database
  190. // now construct the indexes
  191. $index = '';
  192. if ($indexed) {
  193. // add to the array of values
  194. $vals = preg_split("/[\n,]+/", $indexed);
  195. $index = '';
  196. foreach ($vals as $field) {
  197. $field = trim($field);
  198. $index .= "CREATE INDEX idx_${mv_table}_${field} ON $mv_table ($field);";
  199. }
  200. }
  201. // re-create the table differently depending on if it the traditional method
  202. // or the Drupal Schema API method
  203. if ($mv_schema) {
  204. if (!tripal_core_create_custom_table($ret, $mv_table, $schema_arr, 0)) {
  205. drupal_set_message(t("Could not create the materialized view. Check Drupal error report logs."));
  206. }
  207. else {
  208. drupal_set_message(t("View '%name' created", array('%name' => $name)));
  209. }
  210. }
  211. else {
  212. $sql = "CREATE TABLE {$mv_table} ($mv_specs); $index";
  213. $previous_db = tripal_db_set_active('chado'); // use chado database
  214. $results = db_query($sql);
  215. tripal_db_set_active($previous_db); // now use drupal database
  216. if ($results) {
  217. drupal_set_message(t("View '%name' edited and saved. All results cleared. Please re-populate the view.", array('%name' => $name)));
  218. }
  219. else {
  220. drupal_set_message(t("Failed to create the materialized view table: '%mv_table'", array('%mv_table' => $mv_table)), 'error');
  221. }
  222. }
  223. }
  224. }
  225. /**
  226. * Retrieve the materialized view_id given the name
  227. *
  228. * @param $view_name
  229. * The name of the materialized view
  230. *
  231. * @return
  232. * The unique identifier for the given view
  233. *
  234. * @ingroup tripal_mviews_api
  235. */
  236. function tripal_mviews_get_mview_id($view_name) {
  237. $sql = "SELECT * FROM {tripal_mviews} ".
  238. "WHERE name = '%s'";
  239. if (db_table_exists('tripal_mviews')) {
  240. $mview = db_fetch_object(db_query($sql, $view_name));
  241. if ($mview) {
  242. return $mview->mview_id;
  243. }
  244. }
  245. return FALSE;
  246. }
  247. /**
  248. * Does the specified action for the specified Materialized View
  249. *
  250. * @param $op
  251. * The action to be taken. One of update or delete
  252. * @param $mview_id
  253. * The unique ID of the materialized view for the action to be performed on
  254. * @param $redirect
  255. * TRUE/FALSE depending on whether you want to redirect the user to admin/tripal/mviews
  256. *
  257. * @ingroup tripal_core
  258. */
  259. function tripal_mviews_action($op, $mview_id, $redirect = FALSE) {
  260. global $user;
  261. $args = array("$mview_id");
  262. if (!$mview_id) {
  263. return '';
  264. }
  265. // get this mview details
  266. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = %d";
  267. $mview = db_fetch_object(db_query($sql, $mview_id));
  268. // add a job or perform the action based on the given operation
  269. if ($op == 'update') {
  270. tripal_add_job("Populate materialized view '$mview->name'", 'tripal_core',
  271. 'tripal_update_mview', $args, $user->uid);
  272. }
  273. if ($op == 'delete') {
  274. // remove the mview from the tripal_mviews table
  275. $sql = "DELETE FROM {tripal_mviews} ".
  276. "WHERE mview_id = $mview_id";
  277. db_query($sql);
  278. // drop the table from chado if it exists
  279. $previous_db = tripal_db_set_active('chado'); // use chado database
  280. if (db_table_exists($mview->mv_table)) {
  281. $sql = "DROP TABLE $mview->mv_table";
  282. db_query($sql);
  283. }
  284. tripal_db_set_active($previous_db); // now use drupal database
  285. }
  286. // Redirect the user
  287. if ($redirect) {
  288. drupal_goto("admin/tripal/mviews");
  289. }
  290. }
  291. /**
  292. * Update a Materialized View
  293. *
  294. * @param $mview_id
  295. * The unique identifier for the materialized view to be updated
  296. *
  297. * @return
  298. * True if successful, FALSE otherwise
  299. *
  300. * @ingroup tripal_mviews_api
  301. */
  302. function tripal_update_mview($mview_id) {
  303. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = %d ";
  304. $mview = db_fetch_object(db_query($sql, $mview_id));
  305. if ($mview) {
  306. $previous_db = tripal_db_set_active('chado'); // use chado database
  307. $results = db_query("DELETE FROM {%s}", $mview->mv_table);
  308. $results = db_query("INSERT INTO {%s} ($mview->query)", $mview->mv_table);
  309. tripal_db_set_active($previous_db); // now use drupal database
  310. if ($results) {
  311. $sql = "SELECT count(*) as cnt FROM {%s}";
  312. $previous_db = tripal_db_set_active('chado'); // use chado database
  313. $count = db_fetch_object(db_query($sql, $mview->mv_table));
  314. tripal_db_set_active($previous_db); // now use drupal database
  315. $record = new stdClass();
  316. $record->mview_id = $mview_id;
  317. $record->last_update = time();
  318. $record->status = "Populated with " . number_format($count->cnt) . " rows";
  319. drupal_write_record('tripal_mviews', $record, 'mview_id');
  320. return TRUE;
  321. }
  322. else {
  323. // print and save the error message
  324. $record = new stdClass();
  325. $record->mview_id = $mview_id;
  326. $record->status = "ERROR populating. See Drupal's recent log entries for details.";
  327. print $record->status . "\n";
  328. drupal_write_record('tripal_mviews', $record, 'mview_id');
  329. return FALSE;
  330. }
  331. }
  332. }
  333. /**
  334. * A template function which returns markup to display details for the current materialized view
  335. *
  336. * @param $mview_id
  337. * The unique ID of the materialized view to render
  338. *
  339. * @ingroup tripal_mviews_api
  340. */
  341. function tripal_mview_report($mview_id) {
  342. // get this mview details
  343. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = %d";
  344. $mview = db_fetch_object(db_query($sql, $mview_id));
  345. // create a table with each row containig stats for
  346. // an individual job in the results set.
  347. $return_url = url("admin/tripal/mviews/");
  348. $output .= "<p><a href=\"$return_url\">Return to table of materialized views.</a></p>";
  349. $output .= "<br />";
  350. $output .= "<p>Details for <b>$mview->name</b>:</p>";
  351. $output .= "<br />";
  352. $output .= "<table class=\"border-table\">";
  353. if ($mview->name) {
  354. $output .= " <tr>".
  355. " <th>View Name</th>".
  356. " <td>$mview->name</td>".
  357. " </tr>";
  358. }
  359. if ($mview->modulename) {
  360. $output .= " <tr>".
  361. " <th>Module Name</th>".
  362. " <td>$mview->modulename</td>".
  363. " </tr>";
  364. }
  365. if ($mview->mv_table) {
  366. $output .= " <tr>".
  367. " <th>Table Name</th>".
  368. " <td>$mview->mv_table</td>".
  369. " </tr>";
  370. }
  371. if ($mview->mv_specs) {
  372. $output .= " <tr>".
  373. " <th>Table Field Definitions</th>".
  374. " <td>$mview->mv_specs</td>".
  375. " </tr>";
  376. }
  377. if ($mview->query) {
  378. $output .= " <tr>".
  379. " <th>Query</th>".
  380. " <td><pre>$mview->query</pre></td>".
  381. " </tr>";
  382. }
  383. if ($mview->indexed) {
  384. $output .= " <tr>".
  385. " <th>Indexed Fields</th>".
  386. " <td>$mview->indexed</td>".
  387. " </tr>";
  388. }
  389. if ($mview->special_index) {
  390. $output .= " <tr>".
  391. " <th>Special Indexed Fields</th>".
  392. " <td>$mview->speical_index</td>".
  393. " </tr>";
  394. }
  395. if ($mview->last_update > 0) {
  396. $update = format_date($mview->last_update);
  397. }
  398. else {
  399. $update = 'Not yet populated';
  400. }
  401. $output .= " <tr>".
  402. " <th>Last Update</th>".
  403. " <td>$update</td>".
  404. " </tr>";
  405. // build the URLs using the url function so we can handle installations where
  406. // clean URLs are or are not used
  407. $update_url = url("admin/tripal/mviews/action/update/$mview->mview_id");
  408. $delete_url = url("admin/tripal/mviews/action/delete/$mview->mview_id");
  409. $edit_url = url("admin/tripal/mviews/edit/$mview->mview_id");
  410. $output .= "<tr><th>Actions</th>".
  411. "<td> <a href='$update_url'>Populate</a>, ".
  412. " <a href='$edit_url'>Edit</a>, ".
  413. " <a href='$delete_url'>Delete</a></td></tr>";
  414. $output .= "</table>";
  415. return $output;
  416. }
  417. /**
  418. * A template function to render a listing of all Materialized Views
  419. *
  420. * @ingroup tripal_mviews_api
  421. */
  422. function tripal_mviews_report() {
  423. $header = array('', 'MView Name', 'Last Update', 'Status', 'Description', '');
  424. $rows = array();
  425. $mviews = db_query("SELECT * FROM {tripal_mviews} ORDER BY name");
  426. while ($mview = db_fetch_object($mviews)) {
  427. if ($mview->last_update > 0) {
  428. $update = format_date($mview->last_update);
  429. }
  430. else {
  431. $update = 'Not yet populated';
  432. }
  433. $rows[] = array(
  434. l(t('View'), "admin/tripal/mviews/report/$mview->mview_id") ." | ".
  435. l(t('Edit'), "admin/tripal/mviews/edit/$mview->mview_id") ." | ".
  436. l(t('Populate'), "admin/tripal/mviews/action/update/$mview->mview_id"),
  437. $mview->name,
  438. $update,
  439. $mview->status,
  440. $mview->comment,
  441. l(t('Delete'), "admin/tripal/mviews/action/delete/$mview->mview_id"),
  442. );
  443. }
  444. $rows[] = array(
  445. 'data' => array(
  446. array('data' => l(t('Create a new materialized view.'), "admin/tripal/mviews/new"),
  447. 'colspan' => 6),
  448. )
  449. );
  450. $page = theme('table', $header, $rows);
  451. return $page;
  452. }
  453. /**
  454. * A Form to Create/Edit a Materialized View
  455. *
  456. * @param $form_state
  457. * The current state of the form (Form API)
  458. * @param $mview_id
  459. * The unique ID of the Materialized View to Edit or NULL if creating a new materialized view
  460. *
  461. * @return
  462. * A form array (Form API)
  463. *
  464. * @ingroup tripal_core
  465. */
  466. function tripal_mviews_form(&$form_state = NULL, $mview_id = NULL) {
  467. if (!$mview_id) {
  468. $action = 'Add';
  469. }
  470. else {
  471. $action = 'Edit';
  472. }
  473. // get this requested view
  474. if (strcmp($action, 'Edit')==0) {
  475. $sql = "SELECT * FROM {tripal_mviews} WHERE mview_id = %d ";
  476. $mview = db_fetch_object(db_query($sql, $mview_id));
  477. // set the default values. If there is a value set in the
  478. // form_state then let's use that, otherwise, we'll pull
  479. // the values from the database
  480. $default_name = $form_state['values']['name'];
  481. $default_mv_table = $form_state['values']['mv_table'];
  482. $default_mv_specs = $form_state['values']['mv_specs'];
  483. $default_indexed = $form_state['values']['indexed'];
  484. $default_mvquery = $form_state['values']['mvquery'];
  485. $default_special_index = $form_state['values']['special_index'];
  486. $default_comment = $form_state['values']['cpmment'];
  487. if (!$default_name) {
  488. $default_name = $mview->name;
  489. }
  490. if (!$default_mv_table) {
  491. $default_mv_table = $mview->mv_table;
  492. }
  493. if (!$default_mv_specs) {
  494. $default_mv_specs = $mview->mv_specs;
  495. }
  496. if (!$default_indexed) {
  497. $default_indexed = $mview->indexed;
  498. }
  499. if (!$default_mvquery) {
  500. $default_mvquery = $mview->query;
  501. }
  502. if (!$default_special_index) {
  503. $default_special_index = $mview->special_index;
  504. }
  505. if (!$default_comment) {
  506. $default_comment = $mview->comment;
  507. }
  508. if (!$default_schema) {
  509. $default_schema = $mview->mv_schema;
  510. }
  511. // the mv_table column of the tripal_mviews table always has the table
  512. // name even if it is a custom table. However, for the sake of the form,
  513. // we do not want this to show up as the mv_table is needed for the
  514. // traditional style input. We'll blank it out if we have a custom
  515. // table and it will get reset in the submit function using the
  516. // 'table' value from the schema array
  517. if ($default_schema) {
  518. $default_mv_table = '';
  519. }
  520. // set which fieldset is collapsed
  521. $schema_collapsed = 0;
  522. $traditional_collapsed = 1;
  523. if (!$default_schema) {
  524. $schema_collapsed = 1;
  525. $traditional_collapsed = 0;
  526. }
  527. }
  528. // Build the form
  529. $form['action'] = array(
  530. '#type' => 'value',
  531. '#value' => $action
  532. );
  533. $form['mview_id'] = array(
  534. '#type' => 'value',
  535. '#value' => $mview_id
  536. );
  537. $form['name']= array(
  538. '#type' => 'textfield',
  539. '#title' => t('View Name'),
  540. '#description' => t('Please enter the name for this materialized view.'),
  541. '#required' => TRUE,
  542. '#default_value' => $default_name,
  543. );
  544. $form['comment']= array(
  545. '#type' => 'textarea',
  546. '#title' => t('MView Description'),
  547. '#description' => t('Optional. Please provide a description of the purpose for this materialized vieww.'),
  548. '#required' => FALSE,
  549. '#default_value' => $default_comment,
  550. );
  551. // add a fieldset for the Drupal Schema API
  552. $form['schema'] = array(
  553. '#type' => 'fieldset',
  554. '#title' => 'Drupal Schema API Setup',
  555. '#description' => t('Use the Drupal Schema API array to describe a table. The benefit is that it '.
  556. 'can be fully integrated with Tripal Views. Tripal supports an extended '.
  557. 'array format to allow for descriptoin of foreign key relationships.'),
  558. '#collapsible' => 1,
  559. '#collapsed' => $schema_collapsed ,
  560. );
  561. $form['schema']['schema']= array(
  562. '#type' => 'textarea',
  563. '#title' => t('Schema Array'),
  564. '#description' => t('Please enter the Drupal Schema API compatible array that defines the table.'),
  565. '#required' => FALSE,
  566. '#default_value' => $default_schema,
  567. '#rows' => 25,
  568. );
  569. // add a fieldset for the Original Table Description fields
  570. $form['traditional'] = array(
  571. '#type' => 'fieldset',
  572. '#title' => 'Traditional MViews Setup',
  573. '#description' => t('Traidtionally with Tripal MViews were created by specifying PostgreSQL style '.
  574. 'column types. This method can be used but is deprecated in favor of the '.
  575. 'newer Drupal schema API method provided above.'),
  576. '#collapsible' => 1,
  577. '#collapsed' => $traditional_collapsed,
  578. );
  579. $form['traditional']['mv_table']= array(
  580. '#type' => 'textfield',
  581. '#title' => t('Table Name'),
  582. '#description' => t('Please enter the table name that this view will generate in the database. You can use the schema and table name for querying the view'),
  583. '#required' => FALSE,
  584. '#default_value' => $default_mv_table,
  585. );
  586. $form['traditional']['mv_specs']= array(
  587. '#type' => 'textarea',
  588. '#title' => t('Table Definition'),
  589. '#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.'),
  590. '#required' => FALSE,
  591. '#default_value' => $default_mv_specs,
  592. );
  593. $form['traditional']['indexed']= array(
  594. '#type' => 'textarea',
  595. '#title' => t('Indexed Fields'),
  596. '#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.'),
  597. '#required' => FALSE,
  598. '#default_value' => $default_indexed,
  599. );
  600. /**
  601. $form['traditional']['special_index']= array(
  602. '#type' => 'textarea',
  603. '#title' => t('View Name'),
  604. '#description' => t('Please enter the name for this materialized view.'),
  605. '#required' => TRUE,
  606. '#default_value' => $default_special_index,
  607. );
  608. */
  609. $form['mvquery']= array(
  610. '#type' => 'textarea',
  611. '#title' => t('Query'),
  612. '#description' => t('Please enter the SQL statement used to populate the table.'),
  613. '#required' => TRUE,
  614. '#default_value' => $default_mvquery,
  615. '#rows' => 25,
  616. );
  617. if ($action == 'Edit') {
  618. $value = 'Save';
  619. }
  620. if ($action == 'Add') {
  621. $value = 'Add';
  622. }
  623. $form['submit'] = array(
  624. '#type' => 'submit',
  625. '#value' => t($value),
  626. '#weight' => 9,
  627. '#executes_submit_callback' => TRUE,
  628. );
  629. $form['#redirect'] = 'admin/tripal/mviews';
  630. return $form;
  631. }
  632. /**
  633. * Validate the Create/Edit Materialized View Form
  634. * Implements hook_form_validate().
  635. *
  636. * @ingroup tripal_core
  637. */
  638. function tripal_mviews_form_validate($form, &$form_state) {
  639. $action = $form_state['values']['action'];
  640. $mview_id = $form_state['values']['mview_id'];
  641. $name = $form_state['values']['name'];
  642. $mv_table = $form_state['values']['mv_table'];
  643. $mv_specs = $form_state['values']['mv_specs'];
  644. $indexed = $form_state['values']['indexed'];
  645. $query = $form_state['values']['mvquery'];
  646. $special_index = $form_state['values']['special_index'];
  647. $comment = $form_state['values']['comment'];
  648. $schema = $form_state['values']['schema'];
  649. if ($schema and ($mv_table or $mv_specs or $indexed or $special_index)) {
  650. form_set_error($form_state['values']['schema'],
  651. t('You can create an MView using the Drupal Schema API method or the '.
  652. 'traditional method but not both.'));
  653. }
  654. if (!$schema) {
  655. if (!$mv_specs) {
  656. form_set_error($form_state['values']['mv_specs'],
  657. t('The Table Definition field is required.'));
  658. }
  659. if (!$mv_table) {
  660. form_set_error($form_state['values']['mv_table'],
  661. t('The Table Name field is required.'));
  662. }
  663. }
  664. // make sure the array is valid
  665. if ($schema) {
  666. $success = eval("\$schema_array = $schema;");
  667. if ($success === FALSE) {
  668. $error = error_get_last();
  669. form_set_error($form_state['values']['schema'],
  670. t("The schema array is improperly formatted. Parse Error : " . $error["message"]));
  671. }
  672. if (!array_key_exists('table', $schema_array)) {
  673. form_set_error($form_state['values']['schema'],
  674. t("The schema array must have key named 'table'"));
  675. }
  676. // TODO: add in more validation checks of the array to help the user
  677. }
  678. }
  679. /**
  680. * Submit the Create/Edit Materialized View Form
  681. * Implements hook_form_submit().
  682. *
  683. * @ingroup tripal_core
  684. */
  685. function tripal_mviews_form_submit($form, &$form_state) {
  686. $ret = array();
  687. $action = $form_state['values']['action'];
  688. $mview_id = $form_state['values']['mview_id'];
  689. $name = $form_state['values']['name'];
  690. $mv_table = $form_state['values']['mv_table'];
  691. $mv_specs = $form_state['values']['mv_specs'];
  692. $indexed = $form_state['values']['indexed'];
  693. $query = $form_state['values']['mvquery'];
  694. $special_index = $form_state['values']['special_index'];
  695. $comment = $form_state['values']['comment'];
  696. $schema = $form_state['values']['schema'];
  697. if (strcmp($action, 'Edit') == 0) {
  698. tripal_edit_mview($mview_id, $name, 'tripal_core', $mv_table, $mv_specs,
  699. $indexed, $query, $special_index, $comment, $schema);
  700. }
  701. elseif (strcmp($action, 'Add') == 0) {
  702. tripal_add_mview($name, 'tripal_core', $mv_table, $mv_specs,
  703. $indexed, $query, $special_index, $comment, $schema);
  704. }
  705. else {
  706. drupal_set_message(t("No action performed."));
  707. }
  708. return '';
  709. }