tripal_core.custom_tables.api.inc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. <?php
  2. /**
  3. * @file
  4. * Provides an API to manage custom tables in Chado.
  5. */
  6. /**
  7. * @defgroup tripal_custom_tables_api Tripal Custom Tables API
  8. * @ingroup tripal_core_api
  9. * @{
  10. * Provides an API to manage custom tables in Chado.
  11. * @}
  12. */
  13. /**
  14. * Edits a custom table in the chado database. It supports
  15. * using the Drupal Schema API array.
  16. *
  17. * @param $table_id
  18. * The table_id of the table to edit
  19. * @param $table_name
  20. * The name of the custom table
  21. * @param $schema
  22. * Use the Schema API array to define the custom table.
  23. * @param $skip_creation
  24. * Set as TRUE to skip dropping and re-creation of the table. This is
  25. * useful if the table was already created through another means and you
  26. * simply want to make Tripal aware of the table schema.
  27. *
  28. * @ingroup tripal_custom_tables_api
  29. */
  30. function chado_edit_custom_table($table_id, $table_name, $schema, $skip_creation = 1) {
  31. // Create a new record
  32. $record = new stdClass();
  33. $record->table_id = $table_id;
  34. $record->table_name = $table_name;
  35. $record->schema = serialize($schema);
  36. // get the current custom table record
  37. $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_id = :table_id";
  38. $results = db_query($sql, array(':table_id' => $table_id));
  39. $custom_table = $results->fetchObject();
  40. // if the user changed the table name, we want to drop the old one and force
  41. // creation of the new one.
  42. if ($custom_table->table_name != $table_name) {
  43. chado_query("DROP TABLE %s", $custom_table->table_name);
  44. $skip_creation = 0; // we want to create the table
  45. }
  46. // if skip creation is not set, then drop the table from chado if it exists
  47. if (!$skip_creation) {
  48. if (db_table_exists($custom_table->table_name)) {
  49. chado_query("DROP TABLE %s", $custom_table->table_name);
  50. drupal_set_message(t("Custom Table '%name' dropped", array('%name' => $custom_table->table_name)));
  51. }
  52. }
  53. // update the custom table record and re-create the table in Chado
  54. if (drupal_write_record('tripal_custom_tables', $record, 'table_id')) {
  55. // drop the table from chado if it exists
  56. if (!$skip_creation) {
  57. if (db_table_exists($custom_table->table_name)) {
  58. chado_query("DROP TABLE %s", $custom_table->table_name);
  59. drupal_set_message(t("Custom Table '%name' dropped", array('%name' => $custom_table->table_name)));
  60. }
  61. // re-create the table
  62. if (!chado_create_custom_table ($table_name, $schema)) {
  63. drupal_set_message(t("Could not create the custom table. Check Drupal error report logs."));
  64. }
  65. else {
  66. drupal_set_message(t("Custom table '%name' created", array('%name' => $table_name)));
  67. }
  68. }
  69. // TODO: add FK constraints
  70. }
  71. }
  72. /**
  73. * Add a new table to the Chado schema. This function is simply a wrapper for
  74. * the db_create_table() function of Drupal, but ensures the table is created
  75. * inside the Chado schema rather than the Drupal schema. If the table already
  76. * exists then it will be dropped and recreated using the schema provided.
  77. * However, it will only drop a table if it exsits in the tripal_custom_tables
  78. * table. This way the function cannot be used to accidentally alter existing
  79. * non custom tables. If $skip_creation is set then the table is simply
  80. * added to the tripal_custom_tables and no table is created in Chado.
  81. *
  82. * @param $table
  83. * The name of the table to create.
  84. * @param $schema
  85. * A Drupal-style Schema API definition of the table
  86. * @param $skip_creation
  87. * Set as TRUE to skip dropping and re-creation of the table if it already
  88. * exists. This is useful if the table was already created through another
  89. * means and you simply want to make Tripal aware of the table schema. If the
  90. * table does not exist it will be created.
  91. *
  92. * @return
  93. * TRUE on success, FALSE on failure
  94. *
  95. * @ingroup tripal_custom_tables_api
  96. */
  97. function chado_create_custom_table($table, $schema, $skip_creation = 1) {
  98. global $databases;
  99. $created = 0;
  100. $recreated = 0;
  101. // see if the table entry already exists in the tripal_custom_tables table.
  102. $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_name = :table_name";
  103. $results = db_query($sql, array(':table_name' => $table));
  104. $centry = $results->fetchObject();
  105. // check to see if the table already exists in the chado schema
  106. $exists = chado_table_exists($table);
  107. // if the table does not exist then create it
  108. if (!$exists) {
  109. try {
  110. $ret = db_create_table('chado.' . $table, $schema);
  111. $created = 1;
  112. }
  113. catch (Exception $e) {
  114. $error = $e->getMessage();
  115. tripal_report_error('tripal_core', TRIPAL_ERROR,
  116. "Error adding custom table: @message", array('@message' => $error));
  117. drupal_set_message("Could not add custom table. $error.", "error");
  118. return FALSE;
  119. }
  120. }
  121. // if the table exists in Chado and in our custom table and
  122. // skip creation is turned off then drop and re-create the table
  123. if ($exists and is_object($centry) and !$skip_creation) {
  124. // drop the table we'll recreate it with the new schema
  125. try {
  126. chado_query('DROP TABLE {' . $table . '}');
  127. db_create_table('chado.' . $table, $schema);
  128. $recreated = 1;
  129. }
  130. catch (Exception $e) {
  131. $error = $e->getMessage();
  132. tripal_report_error('tripal_core', TRIPAL_ERROR,
  133. "Error adding custom table: @message",
  134. array('@message' => $error));
  135. drupal_set_message("Could not add custom table. $error.", "error");
  136. return FALSE;
  137. }
  138. }
  139. // add an entry in the tripal_custom_table
  140. $record = new stdClass();
  141. $record->table_name = $table;
  142. $record->schema = serialize($schema);
  143. // if an entry already exists then remove it
  144. if ($centry) {
  145. $sql = "DELETE FROM {tripal_custom_tables} WHERE table_name = :table_name";
  146. db_query($sql, array(':table_name' => $table));
  147. }
  148. $success = drupal_write_record('tripal_custom_tables', $record);
  149. if (!$success) {
  150. tripal_report_error('tripal_core', TRIPAL_ERROR,
  151. "Error adding custom table %table_name.",
  152. array('%table_name' => $table));
  153. drupal_set_message(t("Could not add custom table %table_name.
  154. Please check the schema array.", array('%table_name' => $table)), 'error');
  155. return FALSE;
  156. }
  157. // now add any foreign key constraints
  158. if (!$skip_creation and array_key_exists('foreign keys', $schema)) {
  159. // iterate through the foreign keys and add each one
  160. $fkeys = $schema['foreign keys'];
  161. foreach ($fkeys as $fktable => $fkdetails) {
  162. $relations = $fkdetails['columns'];
  163. foreach ($relations as $left => $right) {
  164. $sql = '
  165. ALTER TABLE {' . $table . '}
  166. ADD CONSTRAINT ' . $table . '_' . $left . '_fkey FOREIGN KEY (' . $left . ')
  167. REFERENCES {' . $fktable . '} (' . $right . ')
  168. ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
  169. ';
  170. try {
  171. chado_query($sql);
  172. }
  173. catch (Exception $e) {
  174. $error = $e->getMessage();
  175. tripal_report_error('tripal_core', TRIPAL_ERROR, "Error, could not add foreign key contraint to custom table: %error",
  176. array('%error' => $error));
  177. drupal_set_message("Could not add foreign key contraint to table: $error", 'error');
  178. return FALSE;
  179. }
  180. }
  181. }
  182. }
  183. if ($created) {
  184. drupal_set_message("Custom table created successfully.", 'status');
  185. }
  186. elseif ($recreated) {
  187. drupal_set_message("Custom table re-created successfully.", 'status');
  188. }
  189. else {
  190. drupal_set_message("Custom table already exists. Table structure not changed, but definition array has been saved.", 'status');
  191. }
  192. return TRUE;
  193. }
  194. /**
  195. * Retrieve the custom table id given the name
  196. *
  197. * @param $table_name
  198. * The name of the custom table
  199. *
  200. * @return
  201. * The unique identifier for the given table
  202. *
  203. * @ingroup tripal_custom_tables_api
  204. */
  205. function chado_get_custom_table_id($table_name) {
  206. if (db_table_exists('tripal_custom_tables')) {
  207. $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_name = :table_name";
  208. $results = db_query($sql, array(':table_name' => $table_name));
  209. $custom_table = $results->fetchObject();
  210. if ($custom_table) {
  211. return $custom_table->table_id;
  212. }
  213. }
  214. return FALSE;
  215. }