1
0
mirror of https://github.com/e107inc/e107.git synced 2025-08-12 01:25:01 +02:00

e_db_pdo::copyRow() - Greatly decrease collision chance

Increased possible random strings for unique fields in e_db_pdo::copyRow() from 1000 to 59^11 (UserHandler::generateRandomString() "alphanumeric" should have 59 characters to choose from)

If a collision still happens, e_db_pdo::copyRow() retries up to 3 times for a successful copy.

Fixes: #3678
This commit is contained in:
Nick Liu
2019-12-27 21:54:11 +01:00
parent 5e9b3bee14
commit fabb0c2757
2 changed files with 82 additions and 28 deletions

View File

@@ -2295,42 +2295,47 @@ class e_db_pdo implements e_db
return false;
}
if($fields === '*')
{
$fields = $this->db_FieldList($table);
$unique = $this->_getUnique($table);
for ($retries = 0; $retries < 3; $retries ++) {
if ($fields === '*') {
$fieldList = $this->db_FieldList($table);
$unique = $this->_getUnique($table);
$flds = array();
// randomize fields that must be unique.
foreach($fields as $fld)
{
if(isset($unique[$fld]))
{
$flds[] = $unique[$fld] === 'PRIMARY' ? 0 : "'rand-".rand(0,999)."'"; // keep it short.
continue;
$flds = array();
// randomize fields that must be unique.
foreach ($fieldList as $fld) {
if (isset($unique[$fld])) {
$flds[] = $unique[$fld] === 'PRIMARY' ? 0 :
"'rand-" . e107::getUserSession()->generateRandomString('***********') . "'";
continue;
}
$flds[] = $fld;
}
$flds[] = $fld;
$fieldList = implode(",", $fieldList);
$fieldList2 = implode(",", $flds);
} else {
$fieldList = $fields;
$fieldList2 = $fieldList;
}
$fieldList = implode(",", $fields);
$fieldList2 = implode(",", $flds);
}
else
{
$fieldList = $fields;
$fieldList2 = $fieldList;
}
if (empty($fieldList)) {
$this->mysqlLastErrText = "copyRow \$fields list was empty";
return false;
}
if(empty($fieldList))
{
$this->mysqlLastErrText = "copyRow \$fields list was empty";
return false;
$beforeLastInsertId = $this->lastInsertId();
$id = $this->gen(
"INSERT INTO " . $this->mySQLPrefix . $table .
"(" . $fieldList . ") SELECT " .
$fieldList2 .
" FROM " . $this->mySQLPrefix . $table .
" WHERE " . $args
);
$lastInsertId = $this->lastInsertId();
if ($beforeLastInsertId !== $lastInsertId) break;
}
$id = $this->gen("INSERT INTO ".$this->mySQLPrefix.$table."(".$fieldList.") SELECT ".$fieldList2." FROM ".$this->mySQLPrefix.$table." WHERE ".$args);
$lastInsertId = $this->lastInsertId();
return ($id && $lastInsertId) ? $lastInsertId : false;
}