1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 14:00:56 +01:00
phorge-phorge/resources/sql/autopatches/20210215.changeset.02.phid-populate.php
epriestley 32da29b965 Provide more help around GRANT errors, particularly for missing TEMPORARY TABLE permission
Summary:
Fixes T13622. Figuring out what permissions we have seems difficult, so address this a bit more narrowly:

  - Make the "access denied" error message a bit more helpful.
  - Tailor error handling for the "CREATE TEMPORARY TABLE" statement.

Test Plan:
  - Created a new user, granted them "SELECT ON *.*" but not "CREATE TEMPORARY TABLE", ran `bin/storage upgrade --force --apply phabricator:20210215.changeset.02.phid-populate.php`.
  - Before: fairly opaque error.
  - After: fairly useful error.

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13622

Differential Revision: https://secure.phabricator.com/D21608
2021-03-11 14:55:21 -08:00

79 lines
1.7 KiB
PHP

<?php
$phid_type = DifferentialChangesetPHIDType::TYPECONST;
$changeset_table = new DifferentialChangeset();
$conn = $changeset_table->establishConnection('w');
$table_name = $changeset_table->getTableName();
$chunk_size = 4096;
$temporary_table = 'tmp_20210215_changeset_id_map';
try {
queryfx(
$conn,
'CREATE TEMPORARY TABLE %T (
changeset_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
changeset_phid VARBINARY(64) NOT NULL)',
$temporary_table);
} catch (AphrontAccessDeniedQueryException $ex) {
throw new PhutilProxyException(
pht(
'Failed to "CREATE TEMPORARY TABLE". You may need to "GRANT" the '.
'current MySQL user this permission.'),
$ex);
}
$table_iterator = id(new LiskRawMigrationIterator($conn, $table_name))
->setPageSize($chunk_size);
$chunk_iterator = new PhutilChunkedIterator($table_iterator, $chunk_size);
foreach ($chunk_iterator as $chunk) {
$map = array();
foreach ($chunk as $changeset_row) {
$phid = $changeset_row['phid'];
if (strlen($phid)) {
continue;
}
$phid = PhabricatorPHID::generateNewPHID($phid_type);
$id = $changeset_row['id'];
$map[(int)$id] = $phid;
}
if (!$map) {
continue;
}
$sql = array();
foreach ($map as $changeset_id => $changeset_phid) {
$sql[] = qsprintf(
$conn,
'(%d, %s)',
$changeset_id,
$changeset_phid);
}
queryfx(
$conn,
'TRUNCATE TABLE %T',
$temporary_table);
queryfx(
$conn,
'INSERT INTO %T (changeset_id, changeset_phid) VALUES %LQ',
$temporary_table,
$sql);
queryfx(
$conn,
'UPDATE %T c JOIN %T x ON c.id = x.changeset_id
SET c.phid = x.changeset_phid',
$table_name,
$temporary_table);
}