| 40 | | protected $url; |
|---|
| 41 | | protected $userid; |
|---|
| 42 | | protected $password; |
|---|
| 43 | | protected $dir; |
|---|
| 44 | | protected $outputFile = 'dbdeploy_deploy.sql'; |
|---|
| 45 | | protected $undoOutputFile = 'dbdeploy_undo.sql'; |
|---|
| 46 | | protected $deltaSet = 'Main'; |
|---|
| 47 | | protected $lastChangeToApply = 999; |
|---|
| 48 | | protected $dbmsSyntax = null; |
|---|
| 49 | | |
|---|
| 50 | | function main() { |
|---|
| 51 | | try{ |
|---|
| 52 | | // get correct DbmsSyntax object |
|---|
| 53 | | $dbms = substr($this->url, 0, strpos($this->url, ':')); |
|---|
| 54 | | $dbmsSyntaxFactory = new DbmsSyntaxFactory($dbms); |
|---|
| 55 | | $this->dbmsSyntax = $dbmsSyntaxFactory->getDbmsSyntax(); |
|---|
| 56 | | |
|---|
| 57 | | // open file handles for output |
|---|
| 58 | | $outputFileHandle = fopen($this->outputFile, "w+"); |
|---|
| 59 | | $undoOutputFileHandle = fopen($this->undoOutputFile, "w+"); |
|---|
| 60 | | |
|---|
| 61 | | // figure out which revisions are in the db already |
|---|
| 62 | | $this->appliedChangeNumbers = $this->getAppliedChangeNumbers(); |
|---|
| 63 | | $this->log('Current db revision: ' . $this->getLastChangeAppliedInDb()); |
|---|
| 64 | | |
|---|
| 65 | | // generate sql file needed to take db to "lastChangeToApply" version |
|---|
| 66 | | $doSql = $this->doDeploy(); |
|---|
| 67 | | $undoSql = $this->undoDeploy(); |
|---|
| 68 | | |
|---|
| 69 | | // write the do and undo SQL to their respective files |
|---|
| 70 | | fwrite($outputFileHandle, $doSql); |
|---|
| 71 | | fwrite($undoOutputFileHandle, $undoSql); |
|---|
| 72 | | |
|---|
| 73 | | } catch (Exception $e){ |
|---|
| 74 | | throw new BuildException($e); |
|---|
| 75 | | } |
|---|
| 76 | | } |
|---|
| 77 | | |
|---|
| 78 | | function getAppliedChangeNumbers(){ |
|---|
| 79 | | if(count($this->appliedChangeNumbers) == 0){ |
|---|
| 80 | | $this->log('Getting applied changed numbers from DB: ' . $this->url ); |
|---|
| 81 | | $appliedChangeNumbers = array(); |
|---|
| 82 | | $dbh = new PDO($this->url, $this->userid, $this->password); |
|---|
| 83 | | $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
|---|
| 84 | | $sql = "SELECT * FROM " . DbDeployTask::$TABLE_NAME . " WHERE delta_set = '$this->deltaSet' ORDER BY change_number"; |
|---|
| 85 | | foreach($dbh->query($sql) as $change){ |
|---|
| 86 | | $appliedChangeNumbers[] = $change['change_number']; |
|---|
| 87 | | } |
|---|
| 88 | | $this->appliedChangeNumbers = $appliedChangeNumbers; |
|---|
| 89 | | } |
|---|
| 90 | | return $this->appliedChangeNumbers; |
|---|
| 91 | | } |
|---|
| 92 | | |
|---|
| 93 | | function getLastChangeAppliedInDb(){ |
|---|
| 94 | | return (count($this->appliedChangeNumbers) > 0) ? max($this->appliedChangeNumbers) : 0; |
|---|
| 95 | | } |
|---|
| 96 | | |
|---|
| 97 | | function doDeploy(){ |
|---|
| 98 | | $sqlToPerformDeploy = ''; |
|---|
| 99 | | $lastChangeAppliedInDb = $this->getLastChangeAppliedInDb(); |
|---|
| 100 | | $files = $this->getDeltasFilesArray(); |
|---|
| 101 | | ksort($files); |
|---|
| 102 | | foreach($files as $fileChangeNumber=>$fileName){ |
|---|
| 103 | | if($fileChangeNumber > $lastChangeAppliedInDb && $fileChangeNumber <= $this->lastChangeToApply){ |
|---|
| 104 | | $sqlToPerformDeploy .= '--------------- Fragment begins: ' . $fileChangeNumber . ' ---------------' . "\n"; |
|---|
| 105 | | $sqlToPerformDeploy .= 'INSERT INTO ' . DbDeployTask::$TABLE_NAME . ' (change_number, delta_set, start_dt, applied_by, description)'. |
|---|
| 106 | | ' VALUES ('. $fileChangeNumber .', \''. $this->deltaSet .'\', '. $this->dbmsSyntax->generateTimestamp() .', \'dbdeploy\', \''. $fileName .'\');' . "\n"; |
|---|
| 107 | | $fullFileName = $this->dir . '/' . $fileName; |
|---|
| 108 | | $fh = fopen($fullFileName, 'r'); |
|---|
| 109 | | $contents = fread($fh, filesize($fullFileName)); |
|---|
| 110 | | $deploySQLFromFile = substr($contents,0,strpos($contents, '--//@UNDO')); |
|---|
| 111 | | $sqlToPerformDeploy .= $deploySQLFromFile; |
|---|
| 112 | | $sqlToPerformDeploy .= 'UPDATE ' . DbDeployTask::$TABLE_NAME . ' SET complete_dt = ' . $this->dbmsSyntax->generateTimestamp() . ' WHERE change_number = ' . $fileChangeNumber . ' AND delta_set = \'' . $this->deltaSet . '\';' . "\n"; |
|---|
| 113 | | $sqlToPerformDeploy .= '--------------- Fragment ends: ' . $fileChangeNumber . ' ---------------' . "\n"; |
|---|
| 114 | | } |
|---|
| 115 | | } |
|---|
| 116 | | return $sqlToPerformDeploy; |
|---|
| 117 | | } |
|---|
| 118 | | |
|---|
| 119 | | function undoDeploy(){ |
|---|
| 120 | | $sqlToPerformUndo = ''; |
|---|
| 121 | | $lastChangeAppliedInDb = $this->getLastChangeAppliedInDb(); |
|---|
| 122 | | $files = $this->getDeltasFilesArray(); |
|---|
| 123 | | krsort($files); |
|---|
| 124 | | foreach($files as $fileChangeNumber=>$fileName){ |
|---|
| 125 | | if($fileChangeNumber > $lastChangeAppliedInDb && $fileChangeNumber <= $this->lastChangeToApply){ |
|---|
| 126 | | $fullFileName = $this->dir . '/' . $fileName; |
|---|
| 127 | | $fh = fopen($fullFileName, 'r'); |
|---|
| 128 | | $contents = fread($fh, filesize($fullFileName)); |
|---|
| 129 | | $undoSQLFromFile = substr($contents,strpos($contents, '--//@UNDO')+9); |
|---|
| 130 | | $sqlToPerformUndo .= $undoSQLFromFile; |
|---|
| 131 | | $sqlToPerformUndo .= 'DELETE FROM ' . DbDeployTask::$TABLE_NAME . ' WHERE change_number = ' . $fileChangeNumber . ' AND delta_set = \'' . $this->deltaSet . '\';' . "\n"; |
|---|
| 132 | | $sqlToPerformUndo .= '--------------- Fragment ends: ' . $fileChangeNumber . ' ---------------' . "\n"; |
|---|
| 133 | | } |
|---|
| 134 | | } |
|---|
| 135 | | return $sqlToPerformUndo; |
|---|
| 136 | | } |
|---|
| 137 | | |
|---|
| 138 | | function getDeltasFilesArray(){ |
|---|
| 139 | | $baseDir = realpath($this->dir); |
|---|
| 140 | | $dh = opendir($baseDir); |
|---|
| 141 | | $fileChangeNumberPrefix = ''; |
|---|
| 142 | | while(($file = readdir($dh)) !== false){ |
|---|
| 143 | | if(preg_match('[\d+]', $file, $fileChangeNumberPrefix)){ |
|---|
| 144 | | $files[$fileChangeNumberPrefix[0]] = $file; |
|---|
| 145 | | } |
|---|
| 146 | | } |
|---|
| 147 | | return $files; |
|---|
| 148 | | } |
|---|
| 149 | | |
|---|
| 150 | | function setUrl($url){ |
|---|
| 151 | | $this->url = $url; |
|---|
| | 47 | if ($pkg_info != NULL){ |
|---|
| | 48 | @include_once 'DB/Deploy.php'; |
|---|
| | 49 | $dbdeploy = new Db_Deploy(); |
|---|
| | 50 | $dbdeploy->setConfigFile($this->configFile); |
|---|
| | 51 | $dbdeploy->fire(); |
|---|
| | 52 | } else { |
|---|
| | 53 | throw new BuildException("dbdeploy task depends on PEAR DbDeploy package being installed.", $this->getLocation()); |
|---|
| | 54 | } |
|---|
| | 55 | } catch ( Exception $e ) { |
|---|
| | 56 | throw new BuildException ( $e ) ; |
|---|
| | 57 | } |
|---|