chado_install.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <?php
  2. /**
  3. * @file
  4. * Functions to install chado schema through Drupal
  5. */
  6. /**
  7. * Load Chado Schema 1.11 Form
  8. *
  9. * @ingroup tripal_core
  10. */
  11. function tripal_core_chado_load_form() {
  12. $version = tripal_core_get_chado_version();
  13. $form['current_version'] = array(
  14. '#type' => 'item',
  15. '#title' => t("Current installed version of Chado"),
  16. '#value' => $version,
  17. );
  18. $form['action_to_do'] = array(
  19. '#type' => 'radios',
  20. '#title' => 'Installation/Upgrade Action',
  21. '#options' => array(
  22. 'Install Chado v1.2' => t('New Install of Chado v1.2 (erases all existing Chado data if Chado already exists)'),
  23. 'Upgrade Chado v1.11 to v1.2' => t('Upgrade existing Chado v1.11 to v1.2 (no data is lost)'),
  24. 'Install Chado v1.11' => t('New Install of Chado v1.11 (erases all existing Chado data if Chado already exists)')
  25. ),
  26. '#description' => t('Select an action to perform'),
  27. '#required' => TRUE
  28. );
  29. $form['description'] = array(
  30. '#type' => 'item',
  31. '#value' => t("<font color=\"red\">WARNING:</font> A new install of Chado v1.2 or v1.11 "
  32. ."will install Chado within the Drupal database in a \"chado\" schema. If the \"chado\" schema already exists it will "
  33. ."be overwritten and all data will be lost. You may choose to update an existing Chado v1.11 if it was installed with a previous "
  34. ."version of Tripal (e.g. v0.3b or v0.3.1). The update will not erase any data. "
  35. ."If you are using chado in a database external to the "
  36. ."Drupal database with a 'chado' entry in the 'settings.php' \$db_url argument "
  37. ."then Chado will be installed but will not be used . The external "
  38. ."database specified in the settings.php file takes precedence."),
  39. );
  40. $form['button'] = array(
  41. '#type' => 'submit',
  42. '#value' => t('Install/Upgrade Chado'),
  43. '#weight' => 2,
  44. );
  45. return $form;
  46. }
  47. /**
  48. * Submit Load Chado Schema 1.11 Form
  49. *
  50. * @ingroup tripal_core
  51. */
  52. function tripal_core_chado_load_form_submit($form, &$form_state) {
  53. global $user;
  54. $action_to_do = trim($form_state['values']['action_to_do']);
  55. $args = array($action_to_do);
  56. tripal_add_job($action_to_do, 'tripal_core',
  57. 'tripal_core_install_chado', $args, $user->uid);
  58. }
  59. /**
  60. * Install Chado Schema
  61. *
  62. * @ingroup tripal_core
  63. */
  64. function tripal_core_install_chado($action) {
  65. $vsql = "INSERT INTO chadoprop (type_id, value) VALUES "
  66. ."((SELECT cvterm_id "
  67. ."FROM cvterm CVT "
  68. ." INNER JOIN cv CV on CVT.cv_id = CV.cv_id "
  69. ."WHERE CV.name = 'chado_properties' AND CVT.name = 'version'), "
  70. ."'%s') ";
  71. if($action == 'Install Chado v1.2'){
  72. $schema_file = drupal_get_path('module', 'tripal_core') . '/chado_schema/default_schema-1.2.sql';
  73. $init_file = drupal_get_path('module', 'tripal_core') . '/chado_schema/initialize-1.2.sql';
  74. if (tripal_core_reset_chado_schema()) {
  75. tripal_core_install_sql($schema_file);
  76. tripal_core_install_sql($init_file);
  77. db_query($vsql,'1.2'); # set the version
  78. }
  79. else {
  80. print "ERROR: cannot install chado. Please check database permissions\n";
  81. exit;
  82. }
  83. }
  84. elseif($action == 'Upgrade Chado v1.11 to v1.2') {
  85. $schema_file = drupal_get_path('module', 'tripal_core') . '/chado_schema/default_schema-1.11-1.2-diff.sql';
  86. $init_file = drupal_get_path('module', 'tripal_core') . '/chado_schema/upgrade-1.11-1.2.sql';
  87. tripal_core_install_sql($schema_file);
  88. tripal_core_install_sql($init_file);
  89. db_query($vsql,'1.2'); # set the version
  90. }
  91. elseif($action == 'Install Chado v1.11'){
  92. $schema_file = drupal_get_path('module', 'tripal_core') . '/chado_schema/default_schema-1.11.sql';
  93. $init_file = drupal_get_path('module', 'tripal_core') . '/chado_schema/initialize-1.11.sql';
  94. if (tripal_core_reset_chado_schema()) {
  95. tripal_core_install_sql($schema_file);
  96. tripal_core_install_sql($init_file);
  97. }
  98. else {
  99. print "ERROR: cannot install chado. Please check database permissions\n";
  100. exit;
  101. }
  102. }
  103. }
  104. /**
  105. * Reset the Chado Schema
  106. * This drops the current chado and chado-related schema and re-creates it
  107. *
  108. * @ingroup tripal_core
  109. */
  110. function tripal_core_reset_chado_schema() {
  111. global $active_db;
  112. // drop current chado and chado-related schema
  113. if (tripal_core_schema_exists('chado')) {
  114. print "Dropping existing 'chado' schema\n";
  115. pg_query($active_db, "drop schema chado cascade");
  116. }
  117. if (tripal_core_schema_exists('genetic_code')) {
  118. print "Dropping existing 'genetic_code' schema\n";
  119. pg_query($active_db, "drop schema genetic_code cascade");
  120. }
  121. if (tripal_core_schema_exists('so')) {
  122. print "Dropping existing 'so' schema\n";
  123. pg_query($active_db, "drop schema so cascade");
  124. }
  125. if (tripal_core_schema_exists('frange')) {
  126. print "Dropping existing 'frange' schema\n";
  127. pg_query($active_db, "drop schema frange cascade");
  128. }
  129. // create the new chado schema
  130. print "Creating 'chado' schema\n";
  131. pg_query($active_db, "create schema chado");
  132. if (tripal_core_schema_exists('chado')) {
  133. pg_query($active_db, "create language plpgsql");
  134. return TRUE;
  135. }
  136. return FALSE;
  137. }
  138. /**
  139. * Check that a given schema exists
  140. *
  141. * @param $schema
  142. * The name of the schema to check the existence of
  143. *
  144. * @return
  145. * TRUE/FALSE depending upon whether or not the schema exists
  146. *
  147. * @ingroup tripal_core
  148. */
  149. function tripal_core_schema_exists($schema) {
  150. // check that the chado schema now exists
  151. $sql = "SELECT nspname
  152. FROM pg_namespace
  153. WHERE has_schema_privilege(nspname, 'USAGE') and nspname = '%s'
  154. ORDER BY nspname";
  155. $name = db_fetch_object(db_query($sql, $schema));
  156. if (strcmp($name->nspname, $schema) != 0) {
  157. return FALSE;
  158. }
  159. return TRUE;
  160. }
  161. /**
  162. * Execute the provided SQL
  163. *
  164. * @param $sql_file
  165. * Contains SQL statements to be executed
  166. *
  167. * @ingroup tripal_core
  168. */
  169. function tripal_core_install_sql($sql_file) {
  170. global $active_db;
  171. pg_query($active_db, "set search_path to chado,public");
  172. print "Loading $sql_file...\n";
  173. $lines = file($sql_file, FILE_SKIP_EMPTY_LINES);
  174. if (!$lines) {
  175. return 'Cannot open $schema_file';
  176. }
  177. $stack = array();
  178. $in_string = 0;
  179. $query = '';
  180. $i = 0;
  181. foreach ($lines as $line_num => $line) {
  182. $i++;
  183. $type = '';
  184. // find and remove comments except when inside of strings
  185. if (preg_match('/--/', $line) and !$in_string and !preg_match("/'.*?--.*?'/", $line)) {
  186. $line = preg_replace('/--.*$/', '', $line); // remove comments
  187. }
  188. if (preg_match('/\/\*.*?\*\//', $line)) {
  189. $line = preg_replace('/\/\*.*?\*\//', '', $line); // remove comments
  190. }
  191. // skip empty lines
  192. if (preg_match('/^\s*$/', $line) or strcmp($line, '')==0) {
  193. continue;
  194. }
  195. // Find SQL for new objects
  196. if (preg_match('/^\s*CREATE\s+TABLE/i', $line) and !$in_string) {
  197. $stack[] = 'table';
  198. $line = preg_replace("/public./", "chado.", $line);
  199. }
  200. if (preg_match('/^\s*ALTER\s+TABLE/i', $line) and !$in_string) {
  201. $stack[] = 'alter table';
  202. $line = preg_replace("/public./", "chado.", $line);
  203. }
  204. if (preg_match('/^\s*SET/i', $line) and !$in_string) {
  205. $stack[] = 'set';
  206. }
  207. if (preg_match('/^\s*CREATE\s+SCHEMA/i', $line) and !$in_string) {
  208. $stack[] = 'schema';
  209. }
  210. if (preg_match('/^\s*CREATE\s+SEQUENCE/i', $line) and !$in_string) {
  211. $stack[] = 'sequence';
  212. $line = preg_replace("/public./", "chado.", $line);
  213. }
  214. if (preg_match('/^\s*CREATE\s+(?:OR\s+REPLACE\s+)*VIEW/i', $line) and !$in_string) {
  215. $stack[] = 'view';
  216. $line = preg_replace("/public./", "chado.", $line);
  217. }
  218. if (preg_match('/^\s*COMMENT/i', $line) and !$in_string and sizeof($stack)==0) {
  219. $stack[] = 'comment';
  220. $line = preg_replace("/public./", "chado.", $line);
  221. }
  222. if (preg_match('/^\s*CREATE\s+(?:OR\s+REPLACE\s+)*FUNCTION/i', $line) and !$in_string) {
  223. $stack[] = 'function';
  224. $line = preg_replace("/public./", "chado.", $line);
  225. }
  226. if (preg_match('/^\s*CREATE\s+INDEX/i', $line) and !$in_string) {
  227. $stack[] = 'index';
  228. }
  229. if (preg_match('/^\s*INSERT\s+INTO/i', $line) and !$in_string) {
  230. $stack[] = 'insert';
  231. $line = preg_replace("/public./", "chado.", $line);
  232. }
  233. if (preg_match('/^\s*CREATE\s+TYPE/i', $line) and !$in_string) {
  234. $stack[] = 'type';
  235. }
  236. if (preg_match('/^\s*GRANT/i', $line) and !$in_string) {
  237. $stack[] = 'grant';
  238. }
  239. if (preg_match('/^\s*CREATE\s+AGGREGATE/i', $line) and !$in_string) {
  240. $stack[] = 'aggregate';
  241. }
  242. // determine if we are in a string that spans a line
  243. $matches = preg_match_all("/[']/i", $line, $temp);
  244. $in_string = $in_string - ($matches % 2);
  245. $in_string = abs($in_string);
  246. // if we've reached the end of an object the pop the stack
  247. if (strcmp($stack[sizeof($stack)-1], 'table') == 0 and preg_match('/\);\s*$/', $line)) {
  248. $type = array_pop($stack);
  249. }
  250. if (strcmp($stack[sizeof($stack)-1], 'alter table') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
  251. $type = array_pop($stack);
  252. }
  253. if (strcmp($stack[sizeof($stack)-1], 'set') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
  254. $type = array_pop($stack);
  255. }
  256. if (strcmp($stack[sizeof($stack)-1], 'schema') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
  257. $type = array_pop($stack);
  258. }
  259. if (strcmp($stack[sizeof($stack)-1], 'sequence') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
  260. $type = array_pop($stack);
  261. }
  262. if (strcmp($stack[sizeof($stack)-1], 'view') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
  263. $type = array_pop($stack);
  264. }
  265. if (strcmp($stack[sizeof($stack)-1], 'comment') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
  266. $type = array_pop($stack);
  267. }
  268. if (strcmp($stack[sizeof($stack)-1], 'function') == 0 and preg_match("/LANGUAGE.*?;\s+$/i", $line)) {
  269. $type = array_pop($stack);
  270. }
  271. if (strcmp($stack[sizeof($stack)-1], 'index') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
  272. $type = array_pop($stack);
  273. }
  274. if (strcmp($stack[sizeof($stack)-1], 'insert') == 0 and preg_match('/\);\s*$/', $line)) {
  275. $type = array_pop($stack);
  276. }
  277. if (strcmp($stack[sizeof($stack)-1], 'type') == 0 and preg_match('/\);\s*$/', $line)) {
  278. $type = array_pop($stack);
  279. }
  280. if (strcmp($stack[sizeof($stack)-1], 'grant') == 0 and preg_match('/;\s*$/', $line) and !$in_string) {
  281. $type = array_pop($stack);
  282. }
  283. if (strcmp($stack[sizeof($stack)-1], 'aggregate') == 0 and preg_match('/\);\s*$/', $line)) {
  284. $type = array_pop($stack);
  285. }
  286. // if we're in a recognized SQL statement then let's keep track of lines
  287. if ($type or sizeof($stack) > 0) {
  288. $query .= "$line";
  289. }
  290. else {
  291. print "UNHANDLED $i, $in_string: $line";
  292. return tripal_core_chado_install_done();
  293. }
  294. if (preg_match_all("/\n/", $query, $temp) > 100) {
  295. print "SQL query is too long. Terminating:\n$query\n";
  296. return tripal_core_chado_install_done();
  297. }
  298. if ($type and sizeof($stack) == 0) {
  299. print "Adding $type: line $i\n";
  300. // rewrite the set serach_path to make 'public' be 'chado'
  301. if (strcmp($type, 'set')==0) {
  302. $query = preg_replace("/public/m", "chado", $query);
  303. }
  304. $result = pg_query($active_db, $query);
  305. if (!$result) {
  306. $error = pg_last_error();
  307. print "Installation failed:\nSQL $i, $in_string: $query\n$error\n";
  308. pg_query($active_db, "set search_path to public,chado");
  309. return tripal_core_chado_install_done();
  310. }
  311. $query = '';
  312. }
  313. }
  314. print "Installation Complete!\n";
  315. tripal_core_chado_install_done();
  316. }
  317. /**
  318. * Finish the Chado Schema Installation
  319. *
  320. * @ingroup tripal_core
  321. */
  322. function tripal_core_chado_install_done() {
  323. // return the search path to normal
  324. global $active_db;
  325. pg_query($active_db, "set search_path to public,chado");
  326. }