Include File for Building Schema
<?php /** * Functions for creating and destroying a database schema's contents * * @package Portability * @author Daniel Convissor <danielc@analysisandsolutions.com> * @copyright 2002-2005 The Analysis and Solutions Company * @license http://www.analysisandsolutions.com/software/license.txt Simple Public License * @link http://www.analysisandsolutions.com/presentations/portability/ * @see buildSchema.php, viewSchema.php */ /** * Creates the tables and inserts the initial data * * Goes through each file in the <kbd>./schema</kbd> directory, * extracting the <kbd>CREATE TABLE</kbd> query therein, perform the * column type searches/replaces necessary for the current DBMS type * and then execute the query. * * Then pull the queries from each file in the <kbd>./data</kbd> * directory and execute those. * * @param object $p the portability object * @param object $db the PEAR::DB object * * @return void */ function buildSchema($p, $db) { set_time_limit(0); $dir = dirname(__FILE__); $warn = 0; // Take note of attempts to create something that exists. if (!is_dir("$dir/schema")) { echo "Could not read the $dir/schema directory.\n" . "Creation process terminated.\n"; exit; } if (!is_dir("$dir/data")) { echo "Could not read the $dir/data directory.\n" . "Creation process terminated.\n"; exit; } /* * preg search and replace pairs for create table statements */ $search_create = array( '/REPLSQL-boolean/', '/REPLSQL-clob/', '/REPLSQL-dateliteral/', '/REPLSQL-date/', '/REPLSQL-decimal(\(\d+, *\d+\))/', '/REPLSQL-null/', '/REPLSQL-timestampliteral/', '/REPLSQL-timestamp/', ); $replace_create = array( $p->getBooleanType(), $p->getClobType(), $p->getDateLiteralType(), $p->getDateType(), $p->getDecimalType(), $p->getNullKeyword(), $p->getTimestampLiteralType(), $p->getTimestampType(), ); /* * preg search and replace pairs for data files */ $search_data = array( '/REPLSQL-dateliteral/', '/REPLSQL-false/', '/REPLSQL-true/', '/REPLSQL-timestampliteral/', ); $replace_data = array( $p->getDateLiteralType(), $db->quoteSmart(false), $db->quoteSmart(true), $p->getTimestampLiteralType(), ); /* * Process each schema file */ $dh = opendir("$dir/schema"); while ($file = readdir($dh)) { if (substr($file, -3) == 'sql') { $new_table = true; $schema_file = "$dir/schema/$file"; $fh = fopen($schema_file, 'r'); $contents = ''; while (!feof($fh)) { $line = fgets($fh, 5000); if (substr($line, 0, 2) != '--') { $contents .= $line; } } $contents = preg_replace($search_create, $replace_create, $contents); $queries = preg_split('/;\s*$/m', $contents); foreach ($queries as $query) { if (trim($query) == '') { continue; } $res =& $db->query($query); if (DB::isError($res)) { switch ($res->getCode()) { case DB_ERROR_ALREADY_EXISTS: echo "TABLE OR INDEX ALREADY EXISTS: $file\n"; $warn++; $new_table = false; break; default: echo "---------\nCREATION ERROR in $file\n\n" . $res->getDebugInfo() . "\n---------\nCreation process has been" . " terminated before completion!\n"; exit; } } } if ($new_table) { echo "Executed create: $file\n"; } /* * Process the data file */ $data_file = "$dir/data/$file"; if (file_exists($data_file) && $new_table) { $fh = fopen($data_file, 'r'); while ($line = fgets($fh, 50000)) { if (!preg_match('/^(\s*--|[\r\n]+)/', $line)) { $line = preg_replace('/; *[\r\n]*$/', '', $line); $line = preg_replace($search_data, $replace_data, $line); switch ($db->phptype) { case 'mysql': case 'mysqli': case 'pgsql': $line = str_replace('\\', '\\\\', $line); break; } $res =& $db->query($line); if (DB::isError($res)) { echo "---------\nDATA ERROR in $file\n\n" . $res->getDebugInfo() . "\n---------\nCreation process has been" . " terminated before completion!\n"; exit; } } } echo "Executed data: $file\n"; } } } if ($warn) { echo "\nCompleted table creation.\n\n"; echo "$warn tables or indexes already existed.\n"; echo "They were NOT overwritten.\n\n"; } else { echo "\nSucessfully completed table creation.\n\n"; } } /** * Drops the tables * * Goes through the list of files in the <kbd>./schema</kbd> directory * and drops each table listed there. This works by using the file * names, so don't put multiple create table statements in a schema file. * * This is a simplistic routine, so it doesn't directly drop indexes. * So, if the DBMS doesn't drop indexes automatically when the table they * relate to are dropped, you'll have to do that manually. * * @param object $p the portability object * @param object $db the PEAR::DB object * * @return void */ function dropSchema($p, $db) { set_time_limit(0); $dir = dirname(__FILE__); $warn = 0; // Take note of attempts to drop things that don't exist. if (!is_dir("$dir/schema")) { echo "Could not read the $dir/schema directory.\n" . "Drop process terminated.\n"; exit; } $dh = opendir("$dir/schema"); while ($file = readdir($dh)) { if (substr($file, -3) == 'sql') { $table = basename($file, '.sql'); $res =& $db->query("DROP TABLE $table " . $p->getDropRestrict()); if (DB::isError($res)) { switch ($res->getCode()) { case DB_ERROR_NOSUCHTABLE: case DB_ERROR_NOT_FOUND: echo "TABLE DIDN'T EXIST: $table\n"; break; default: echo "-----\nCOULDN'T DELETE: $table\n"; echo $res->getDebugInfo(); echo "-----\n\n"; } $warn++; continue; } echo 'Dropped: ' . $table . "\n"; } } if ($warn) { echo "\n$warn tables or indexes could not be deleted.\n\n"; } else { echo "\nSucessfully completed table drops.\n\n"; } }