Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions .github/workflows/sql.yml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,12 @@ public static function getColumnDefinition($optionType)
case 'boolean':
$column['notNull'] = true;
$column['default'] = 0;
$column['length'] = 1;
$column['type'] = 'tinyint';
break;

case 'integer':
$column['notNull'] = true;
$column['default'] = 0;
$column['length'] = 10;
$column['type'] = 'int';
break;

Expand Down
138 changes: 97 additions & 41 deletions wcfsetup/install/files/lib/system/WCFSetup.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use wcf\system\database\Database;
use wcf\system\database\exception\DatabaseException;
use wcf\system\database\MySQLDatabase;
use wcf\system\database\table\DatabaseTableChangeProcessor;
use wcf\system\database\util\SQLParser;
use wcf\system\devtools\DevtoolsSetup;
use wcf\system\exception\SystemException;
Expand Down Expand Up @@ -200,7 +201,7 @@ protected function calcProgress(int $currentStep): void
\file_put_contents(\TMP_DIR . 'lastStep', $currentStep);

// calculate progress
$progress = \round((100 / 22) * ++$currentStep, 0);
$progress = \round((100 / 14) * ++$currentStep, 0);
self::getTPL()->assign(['progress' => $progress]);
}

Expand Down Expand Up @@ -275,23 +276,23 @@ protected function dispatch(): ResponseInterface
return $this->createDB();

case 'unzipFiles':
$this->calcProgress(18);
$this->calcProgress(10);
$this->assertNotUnzipped();

return $this->unzipFiles();

case 'installLanguage':
$this->calcProgress(19);
$this->calcProgress(11);

return $this->installLanguage();

case 'createUser':
$this->calcProgress(20);
$this->calcProgress(12);

return $this->createUser();

case 'installPackages':
$this->calcProgress(21);
$this->calcProgress(13);

return $this->installPackages();

Expand Down Expand Up @@ -663,58 +664,113 @@ protected function createDB(): ResponseInterface
{
$this->initDB();

// get content of the sql structure file
$sql = \file_get_contents(TMP_DIR . 'setup/db/install.sql');
$dbEditor = self::getDB()->getEditor();

$tableNames = $dbEditor->getTableNames();
if (!\in_array('wcf1_package_installation_sql_log', $tableNames)) {
$dbEditor->createTable('wcf1_package_installation_sql_log', [
['name' => 'packageID', 'data' => ['type' => 'int', 'notNull' => true]],
['name' => 'sqlTable', 'data' => ['type' => 'varchar', 'length' => 100, 'notNull' => true, 'default' => "''"]],
['name' => 'sqlColumn', 'data' => ['type' => 'varchar', 'length' => 100, 'notNull' => true, 'default' => "''"]],
['name' => 'sqlIndex', 'data' => ['type' => 'varchar', 'length' => 100, 'notNull' => true, 'default' => "''"]],
['name' => 'isDone', 'data' => ['type' => 'tinyint', 'notNull' => true, 'default' => 1]],
], [
[
'name' => 'packageID',
'data' => ['type' => 'UNIQUE', 'columns' => 'packageID,sqlTable,sqlColumn,sqlIndex'],
]
]);

// split by offsets
$sqlData = \explode('/* SQL_PARSER_OFFSET */', $sql);
$offset = isset($_POST['offset']) ? \intval($_POST['offset']) : 0;
if (!isset($sqlData[$offset])) {
throw new SystemException("Offset for SQL parser is out of bounds, " . $offset . " was requested, but there are only " . \count($sqlData) . " sections");
$sql = "INSERT INTO wcf1_package_installation_sql_log
(packageID, sqlTable, isDone)
VALUES (?, ?, ?)";
$statement = self::getDB()->prepareUnmanaged($sql);
$statement->execute([1, 'wcf1_package_installation_sql_log', 1]);
}
$sql = $sqlData[$offset];

// execute sql queries
$parser = new SQLParser($sql);
$parser->execute();
$package = new \wcf\data\package\Package(null, ['packageID' => 1, 'package' => 'com.woltlab.wcf']);
$hasPackageTable = false;
$tables = require \TMP_DIR . 'setup/db/install_com.woltlab.wcf.php';

$completed = false;
$processor = new DatabaseTableChangeProcessor(
$package,
null,
$dbEditor,
);
for ($i = 0; $i < 50; $i++) {
$this->createPseudoPackage();

// log sql queries
\preg_match_all("~CREATE\\s+TABLE\\s+(\\w+)~i", $sql, $matches);
if ($processor->process($tables)) {
continue;
}

$sql = "INSERT INTO wcf1_package_installation_sql_log
(packageID, sqlTable)
VALUES (?, ?)";
$statement = self::getDB()->prepare($sql);
foreach ($matches[1] as $tableName) {
$statement->execute([1, $tableName]);
$completed = true;
break;
}

if ($offset < (\count($sqlData) - 1)) {
if (!$completed) {
$offset = isset($_POST['offset']) ? \intval($_POST['offset']) : 0;
WCF::getTPL()->assign([
'__additionalParameters' => [
'offset' => $offset + 1,
],
]);

return $this->gotoNextStep('createDB');
} else {
/*
* Manually install PIPPackageInstallationPlugin since install.sql content is not escaped resulting
* in different behaviour in MySQL and MSSQL. You SHOULD NOT move this into install.sql!
*/
$sql = "INSERT INTO wcf1_package_installation_plugin
(packageID, pluginName, priority, className)
VALUES (?, ?, ?, ?)";
$statement = self::getDB()->prepare($sql);
$statement->execute([
1,
'packageInstallationPlugin',
1,
'wcf\system\package\plugin\PIPPackageInstallationPlugin',
]);
}

$sql = \explode(
"\n",
\file_get_contents(TMP_DIR . 'setup/db/install.sql')
);
foreach ($sql as $line) {
$line = StringUtil::trim($line);
if ($line === '' || \str_starts_with($line, '-- ')) {
continue;
}

WCF::getDB()->prepareUnmanaged($line)->execute();
}

return $this->gotoNextStep('unzipFiles');
}

/**
* Dynamically creates the pseudo row in `wcf1_package` after the table has
* been created. This step is necessary to preserve the integrity of the
* foreign key enforced on the SQL log and PIP table.
*/
private function createPseudoPackage(): void
{
static $hasPseudoPackage = false;
if ($hasPseudoPackage) {
return;
}

return $this->gotoNextStep('unzipFiles');
$sql = "SHOW TABLES FROM " . self::getDB()->getDatabaseName() . " LIKE 'wcf1_package'";
$statement = self::getDB()->prepareUnmanaged($sql);
$statement->execute([]);
$hasTable = $statement->fetchSingleRow();
if ($hasTable === false) {
return;
}

$sql = "SELECT *
FROM wcf1_package
WHERE packageID = ?";
$statement = self::getDB()->prepareUnmanaged($sql);
$statement->execute([1]);
$row = $statement->fetchSingleRow();
if ($row === false) {
$sql = "INSERT INTO wcf1_package
(packageID, package)
VALUES (?, ?)";
$statement = self::getDB()->prepareUnmanaged($sql);
$statement->execute([1, 'com.woltlab.wcf']);
}

$hasPseudoPackage = true;
}

/**
Expand Down
Loading