Example #1
0
 protected function safeUpdate($stmts, $criteria, $deleteSql, $datas, $fields = null)
 {
     $stmts['existed']->execute($criteria);
     $existedIds = $stmts['existed']->fetchAll(\PDO::FETCH_COLUMN);
     $stmts['existed']->closeCursor();
     /* prepare insertData and updateData */
     $insertData = [];
     $updateData = [];
     $keepIds = [];
     foreach ($datas as $data) {
         if (!empty($data['id']) && in_array($data['id'], $existedIds)) {
             $updateData[] = $data;
             $keepIds[] = $data['id'];
         } else {
             $insertData[] = $data;
         }
     }
     /* delete existed data */
     $inParams = [];
     $undeleteSql = "AND (id NOT IN (" . PDO::prepareIn(':_undeleted_', $keepIds, $inParams) . "))";
     $stmt = $this->getPdo()->prepare(sprintf($deleteSql, empty($inParams) ? "" : $undeleteSql));
     $stmt->execute(array_merge($criteria, $inParams));
     $stmt->closeCursor();
     $fields_update = null;
     $fields_insert = null;
     if (is_array($fields)) {
         if (array_key_exists('update', $fields)) {
             $fields_update = $fields['update'];
         }
         if (array_key_exists('insert', $fields)) {
             $fields_insert = $fields['insert'];
         }
     }
     /* update data before insert to prevent conflict constrain */
     $driver = $this->getPdo()->getAttribute(\PDO::ATTR_DRIVER_NAME);
     $tryUpdateData = $updateData;
     $lastLength = count($tryUpdateData) + 1;
     $lastExcp = null;
     while (count($tryUpdateData) > 0) {
         if ($lastLength == count($tryUpdateData)) {
             throw $lastExcp;
         }
         $nextUpdateData = [];
         $lastLength = count($tryUpdateData);
         foreach ($tryUpdateData as $data) {
             if ($driver == 'pgsql') {
                 $this->getPdo()->query("SAVEPOINT tryupdate_child_data_if_avaliable");
             }
             try {
                 $stmts['update']->execute($fields_update !== null ? array_intersect_key($data, array_flip($fields_update)) : $data);
             } catch (\PDOException $excp) {
                 $lastExcp = $excp;
                 $nextUpdateData[] = $data;
                 if ($driver == 'pgsql') {
                     $this->getPdo()->query("ROLLBACK TO SAVEPOINT tryupdate_child_data_if_avaliable");
                 }
             }
             if ($driver == 'pgsql') {
                 $this->getPdo()->query("RELEASE SAVEPOINT tryupdate_child_data_if_avaliable");
             }
             $stmts['update']->closeCursor();
             $tryUpdateData = $nextUpdateData;
         }
     }
     /* insert data */
     foreach ($insertData as $data) {
         $stmts['insert']->execute($fields_insert !== null ? array_intersect_key($data, array_flip($fields_insert)) : $data);
         $stmts['insert']->closeCursor();
     }
 }