chado_install.php 11 KB

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