Beispiel #1
0
 /**
  * Applies a series of SQL patches to the database and registers them in the db_patches table.
  *
  * @param bool $register_only Only register the patches as done, don't run their code
  * @throws \LemonWeb\Deployer\Exceptions\DatabaseException
  */
 public function update($register_only = false)
 {
     $this->logger->log('Database update: ' . implode(', ', array_keys($this->sql_patch_objects)), LOG_DEBUG, true);
     if (!count($this->sql_patch_objects)) {
         return;
     }
     foreach ($this->sql_patch_objects as $filename => $sql_patch_object) {
         $patch_name = DatabaseHelper::getClassnameFromFilepath($filename);
         $patch_timestamp = DatabaseHelper::convertFilenameToDateTime($filename);
         // Register the patch in the db_patches table (except for the db_patches table patch itself, that wouldn't be possible yet).
         // Add the revert (down) code to the record so the update can be reverted when the file doesn't exist, which can happen when code is rolled back.
         // Also add the patch' dependencies list so depending patches won't be reverted before it is reverted first.
         if ('19700101000000' != $patch_timestamp) {
             $this->driver->query("\n                    INSERT INTO db_patches (\n                        patch_name,\n                        patch_timestamp,\n                        down_sql,\n                        dependencies\n                    )\n                    VALUES (\n                        '" . $this->driver->escape($patch_name) . "',\n                        '" . $this->driver->escape($patch_timestamp) . "',\n                        " . (trim($sql_patch_object->down()) != '' ? "'" . $this->driver->escape(trim($sql_patch_object->down())) . "'" : 'null') . ",\n                        " . (count($sql_patch_object->getDependencies()) > 0 ? "'" . $this->driver->escape(implode("\n", $sql_patch_object->getDependencies())) . "'" : 'null') . "\n                    );\n                ");
         }
         // apply the patch
         if (!$register_only) {
             $this->driver->startTransaction();
             $result = $this->driver->multiQuery($sql_patch_object->up());
             if (false === $result) {
                 throw new DatabaseException('Error applying patch ' . $patch_name . ': ' . $this->driver->getLastError(), 1);
             } else {
                 $this->driver->closeResult($result);
             }
             $this->driver->doCommit();
         }
         // if there were no errors, mark the patch as applied
         if ('19700101000000' != $patch_timestamp) {
             $this->driver->query("\n                    UPDATE db_patches\n                    SET applied_at = '" . $this->driver->escape($this->timestamp) . "'\n                    WHERE patch_name = '" . $this->driver->escape($patch_name) . "';\n                ");
             if ($register_only) {
                 $this->logger->log("Patch '{$filename}' registered.");
             } else {
                 $this->logger->log("Patch '{$filename}' succeeded.");
             }
         } else {
             // the db_patches patch has no record set, insert it now
             $this->driver->query("\n                    INSERT INTO db_patches (\n                        patch_name,\n                        patch_timestamp,\n                        applied_at\n                    )\n                    VALUES (\n                        '" . $this->driver->escape($patch_name) . "',\n                        '" . $this->driver->escape($patch_timestamp) . "',\n                        '" . $this->driver->escape($this->timestamp) . "'\n                    );\n                ");
             $this->logger->log("Patch '{$filename}' succeeded.");
         }
     }
 }