tripal_core.chado_schema.api.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <?php
  2. /**
  3. * @defgroup tripal_chado_schema_api Chado Schema API
  4. * @ingroup tripal_chado_api
  5. * @{
  6. * Provides an application programming interface (API) for describing Chado tables.
  7. * This API consists of a set of functions, one for each table in Chado. Each
  8. * function simply returns a Drupal style array that defines the table.
  9. *
  10. * Because Drupal 6 does not handle foreign key (FK) relationships, however FK
  11. * relationships are needed to for Tripal Views. Therefore, FK relationships
  12. * have been added to the schema defintitions below.
  13. *
  14. * The functions provided in this documentation should not be called as is, but if you need
  15. * the Drupal-style array definition for any table, use the following function
  16. * call:
  17. *
  18. * $table_desc = chado_get_schema($table)
  19. *
  20. * where the variable $table contains the name of the table you want to
  21. * retireve. The chado_get_schema function determines the appropriate version of
  22. * Chado and uses the Drupal hook infrastructure to call the appropriate
  23. * hook function to retrieve the table schema.
  24. * @}
  25. */
  26. /**
  27. * Check that any given Chado table exists. This function
  28. * is necessary because Drupa's db_table_exists will not
  29. * look in any other schema but the one were Drupal is installed
  30. *
  31. * @param $table
  32. * The name of the chado table whose existence should be checked.
  33. * @return
  34. * TRUE if the table exists in the chado schema and FALSE if it does not.
  35. *
  36. * @ingroup tripal_chado_schema_api
  37. */
  38. function chado_table_exists($table) {
  39. global $databases;
  40. $default_db = $databases['default']['default']['database'];
  41. $sql = "
  42. SELECT 1
  43. FROM information_schema.tables
  44. WHERE
  45. table_name = :table_name AND
  46. table_schema = :chado AND
  47. table_catalog = :default_db
  48. ";
  49. $results = db_query($sql, array(':table_name' => $table, ':chado' => tripal_get_schema_name('chado'), ':default_db' => $default_db));
  50. $exists = $results->fetchObject();
  51. if (!$exists) {
  52. return FALSE;
  53. }
  54. return TRUE;
  55. }
  56. /**
  57. * A Chado-aware replacement for the db_index_exists() function.
  58. *
  59. * @param $table
  60. * The table to be altered.
  61. * @param $name
  62. * The name of the index.
  63. */
  64. function chado_index_exists($table, $name) {
  65. global $databases;
  66. $indexname = $table . '_' . $name . '_idx';
  67. $default_db = $databases['default']['default']['database'];
  68. $sql = "SELECT 1 as exists FROM pg_indexes WHERE indexname = :indexname";
  69. $result = db_query($sql, array(':indexname' => $indexname));
  70. $exists = $result->fetchObject();
  71. return $exists->exists;
  72. }
  73. /**
  74. * A Chado-aware wrapper for the db_add_index() function.
  75. *
  76. * @param $table
  77. * The table to be altered.
  78. * @param $name
  79. * The name of the index.
  80. * @param $fields
  81. * An array of field names.
  82. */
  83. function chado_add_index($table, $name, $fields) {
  84. $indexname = $table . '_' . $name . '_idx';
  85. $query = 'CREATE INDEX "' . $indexname . '" ON {' . $table . '} ';
  86. $query .= '(';
  87. $temp = array();
  88. foreach ($fields as $field) {
  89. if (is_array($field)) {
  90. $temp[] = 'substr(' . $field[0] . ', 1, ' . $field[1] . ')';
  91. }
  92. else {
  93. $temp[] = '"' . $field . '"';
  94. }
  95. }
  96. $query .= implode(', ', $temp);
  97. $query .= ')';
  98. return chado_query($query);
  99. }
  100. /**
  101. * Check that any given schema exists.
  102. *
  103. * @param $schema
  104. * The name of the schema to check the existence of
  105. *
  106. * @return
  107. * TRUE/FALSE depending upon whether or not the schema exists
  108. *
  109. * @ingroup tripal_chado_schema_api
  110. */
  111. function chado_dbschema_exists($schema) {
  112. $sql = "
  113. SELECT nspname
  114. FROM pg_namespace
  115. WHERE
  116. has_schema_privilege(nspname, 'USAGE') AND
  117. nspname = :nspname
  118. ORDER BY nspname
  119. ";
  120. $schema = db_query($sql, array(':nspname' => $schema))->fetchField();
  121. if ($schema) {
  122. return TRUE;
  123. }
  124. return FALSE;
  125. }
  126. /**
  127. * Check that the Chado schema exists within the local database
  128. *
  129. * @return
  130. * TRUE/FALSE depending upon whether it exists
  131. *
  132. * @ingroup tripal_chado_schema_api
  133. */
  134. function chado_is_local() {
  135. // This is postgresql-specific code to check the existence of the chado schema
  136. // @coder-ignore: acting on pg_catalog schema rather then drupal schema therefore, table prefixing does not apply
  137. $sql = "
  138. SELECT nspname
  139. FROM pg_namespace
  140. WHERE
  141. has_schema_privilege(nspname, 'USAGE') AND
  142. nspname = :chado
  143. ";
  144. $results = db_query($sql, array(':chado' => tripal_get_schema_name('chado')));
  145. $name = $results->fetchObject();
  146. if ($name) {
  147. variable_set('chado_schema_exists', FALSE);
  148. return TRUE;
  149. }
  150. else {
  151. variable_set('chado_schema_exists', TRUE);
  152. return FALSE;
  153. }
  154. }
  155. /**
  156. * Check whether chado is installed (either in the same or a different database)
  157. *
  158. * @return
  159. * TRUE/FALSE depending upon whether chado is installed.
  160. *
  161. * @ingroup tripal_chado_schema_api
  162. */
  163. function chado_is_installed() {
  164. global $databases;
  165. // first check if chado is in the $databases variable of the settings.php file
  166. if (array_key_exists(tripal_get_schema_name('chado'), $databases)) {
  167. return TRUE;
  168. }
  169. // check to make sure the chado schema exists
  170. return chado_is_local();
  171. }
  172. /**
  173. * Returns the version number of the currently installed Chado instance.
  174. * It can return the real or effective version. Note, this function
  175. * is executed in the hook_init() of the tripal_core module which then
  176. * sets the $GLOBAL['exact_chado_version'] and $GLOBAL['chado_version']
  177. * variable. You can access these variables rather than calling this function.
  178. *
  179. * @param $exact
  180. * Set this argument to 1 to retrieve the exact version that is installed.
  181. * Otherwise, this function will set the version to the nearest 'tenth'.
  182. * Chado versioning numbers in the hundreds represent changes to the
  183. * software and not the schema. Changes in the tenth's represent changes
  184. * in the schema.
  185. *
  186. * @param $warn_if_unsupported
  187. * If the currently installed version of Chado is not supported by Tripal
  188. * this generates a Drupal warning.
  189. *
  190. * @returns
  191. * The version of Chado
  192. *
  193. * @ingroup tripal_chado_schema_api
  194. */
  195. function chado_get_version($exact = FALSE, $warn_if_unsupported = FALSE) {
  196. global $databases;
  197. $version = '';
  198. $is_local = 0;
  199. // check that Chado is installed if not return 'uninstalled as the version'
  200. $chado_exists = chado_is_local();
  201. if (!$chado_exists) {
  202. // if it's not in the drupal database check to see if it's specified in the $db_url
  203. // in the settings.php
  204. if (!array_key_exists(tripal_get_schema_name('chado'), $databases)) {
  205. // if it's not in the drupal database or specified in the $db_url then
  206. // return uninstalled as the version
  207. return 'not installed';
  208. }
  209. $is_local = 0;
  210. $previous_db = chado_set_active('chado');
  211. $prop_exists = db_table_exists('chadoprop');
  212. chado_set_active($previous_db);
  213. }
  214. else {
  215. $is_local = 1;
  216. // @todo we need a chado aware db_table_exists.
  217. $prop_exists = db_table_exists(tripal_get_schema_name('chado').'.chadoprop');
  218. }
  219. // if the table doesn't exist then we don't know what version but we know
  220. // it must be 1.11 or older.
  221. if (!$prop_exists) {
  222. $version = "1.11 or older";
  223. }
  224. else {
  225. $sql = "
  226. SELECT value
  227. FROM {chadoprop} CP
  228. INNER JOIN {cvterm} CVT on CVT.cvterm_id = CP.type_id
  229. INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id
  230. WHERE CV.name = 'chado_properties' and CVT.name = 'version'
  231. ";
  232. if (!$is_local) {
  233. $previous_db = chado_set_active('chado');
  234. $results = db_query($sql);
  235. chado_set_active($previous_db);
  236. }
  237. else {
  238. $results = chado_query($sql);
  239. }
  240. $v = $results->fetchObject();
  241. // if we don't have a version in the chadoprop table then it must be
  242. // v1.11 or older
  243. if (!$v) {
  244. $version = "1.11 or older";
  245. }
  246. else {
  247. $version = $v->value;
  248. }
  249. }
  250. // next get the exact Chado version that is installed
  251. $exact_version = $version;
  252. // Tripal only supports v1.11 or newer.. really this is the same as v1.1
  253. // but at the time the v1.11 schema API was written we didn't know that so
  254. // we'll return the version 1.11 so the schema API will work.
  255. if (strcmp($exact_version, '1.11 or older') == 0) {
  256. $exact_version = "1.11";
  257. if ($warn_if_unsupported) {
  258. drupal_set_message(t("WARNING: Tripal does not fully support Chado version less than v1.11. If you are certain this is v1.11
  259. or if Chado was installed using an earlier version of Tripal then all is well. If not please upgrade to v1.11 or later"),
  260. 'warning');
  261. }
  262. }
  263. // if not returing an exact version, return the version to the nearest 10th.
  264. // return 1.2 for all versions of 1.2x
  265. $effective_version = $exact_version;
  266. if (preg_match('/^1\.2\d+$/', $effective_version)) {
  267. $effective_version = "1.2";
  268. }
  269. if ($warn_if_unsupported and ($effective_version < 1.11 and $effective_version != 'not installed')) {
  270. drupal_set_message(t("WARNING: The currently installed version of Chado, v$exact_version, is not fully compatible with Tripal."), 'warning');
  271. }
  272. // if the callee has requested the exact version then return it
  273. if ($exact) {
  274. return $exact_version;
  275. }
  276. return $effective_version;
  277. }
  278. /**
  279. * Retrieves the list of tables in the Chado schema. By default it only returns
  280. * the default Chado tables, but can return custom tables added to the
  281. * Chado schema if requested
  282. *
  283. * @param $include_custom
  284. * Optional. Set as TRUE to include any custom tables created in the
  285. * Chado schema. Custom tables are added to Chado using the
  286. * tripal_core_chado_create_table() function.
  287. *
  288. * @returns
  289. * An associative array where the key and value pairs are the Chado table names.
  290. *
  291. * @ingroup tripal_chado_schema_api
  292. */
  293. function chado_get_table_names($include_custom = NULL) {
  294. // first get the chado version that is installed
  295. $v = $GLOBALS["chado_version"];
  296. $tables = array();
  297. if ($v == '1.3') {
  298. $tables_v1_3 = tripal_core_chado_get_v1_3_tables();
  299. foreach ($tables_v1_3 as $table) {
  300. $tables[$table] = $table;
  301. }
  302. }
  303. if ($v == '1.2') {
  304. $tables_v1_2 = tripal_core_chado_get_v1_2_tables();
  305. foreach ($tables_v1_2 as $table) {
  306. $tables[$table] = $table;
  307. }
  308. }
  309. if ($v == '1.11' or $v == '1.11 or older') {
  310. $tables_v1_11 = tripal_core_chado_get_v1_11_tables();
  311. foreach ($tables_v1_11 as $table) {
  312. $tables[$table] = $table;
  313. }
  314. }
  315. // now add in the custom tables too if requested
  316. if ($include_custom) {
  317. $sql = "SELECT table_name FROM {tripal_custom_tables}";
  318. $resource = db_query($sql);
  319. foreach ($resource as $r) {
  320. $tables[$r->table_name] = $r->table_name;
  321. }
  322. }
  323. asort($tables);
  324. return $tables;
  325. }
  326. /**
  327. * Retrieves the chado tables Schema API array.
  328. *
  329. * @param $table
  330. * The name of the table to retrieve. The function will use the appopriate
  331. * Tripal chado schema API hooks (e.g. v1.11 or v1.2).
  332. *
  333. * @returns
  334. * A Drupal Schema API array defining the table.
  335. *
  336. * @ingroup tripal_chado_schema_api
  337. */
  338. function chado_get_schema($table) {
  339. // first get the chado version that is installed
  340. $v = $GLOBALS["chado_version"];
  341. // get the table array from the proper chado schema
  342. $v = preg_replace("/\./", "_", $v); // reformat version for hook name
  343. // Call the module_invoke_all.
  344. $hook_name = "chado_schema_v" . $v . "_" . $table;
  345. $table_arr = module_invoke_all($hook_name);
  346. // If the module_invoke_all returned nothing then let's make sure there isn't
  347. // An API call we can call directly. The only time this occurs is
  348. // during an upgrade of a major Drupal version and tripal_core is disabled.
  349. if ((!$table_arr or !is_array($table_arr)) and
  350. function_exists('tripal_core_' . $hook_name)) {
  351. $api_hook = "tripal_core_" . $hook_name;
  352. $table_arr = $api_hook();
  353. }
  354. // if the table_arr is empty then maybe this is a custom table
  355. if (!is_array($table_arr) or count($table_arr) == 0) {
  356. $table_arr = chado_get_custom_table_schema($table);
  357. }
  358. return $table_arr;
  359. }
  360. /**
  361. * Retrieves the schema in an array for the specified custom table.
  362. *
  363. * @param $table
  364. * The name of the table to create.
  365. *
  366. * @return
  367. * A Drupal-style Schema API array definition of the table. Returns
  368. * FALSE on failure.
  369. *
  370. * @ingroup tripal_chado_schema_api
  371. */
  372. function chado_get_custom_table_schema($table) {
  373. $sql = "SELECT schema FROM {tripal_custom_tables} WHERE table_name = :table_name";
  374. $results = db_query($sql, array(':table_name' => $table));
  375. $custom = $results->fetchObject();
  376. if (!$custom) {
  377. return FALSE;
  378. }
  379. else {
  380. return unserialize($custom->schema);
  381. }
  382. }