From 236a4e4e4c5541d7bacf3ba377a0610465655e08 Mon Sep 17 00:00:00 2001
From: Tim van Dijen <tvdijen@gmail.com>
Date: Sat, 31 Aug 2019 14:51:48 +0200
Subject: [PATCH] Rationalize SQL Store insertOrUpdate (#1193)

* Rationalize SQL Store insertOrUpdate
---
 lib/SimpleSAML/Store/SQL.php | 69 +++++++++++++++++-------------------
 1 file changed, 33 insertions(+), 36 deletions(-)

diff --git a/lib/SimpleSAML/Store/SQL.php b/lib/SimpleSAML/Store/SQL.php
index 82d68f66e..3ec9caa4c 100644
--- a/lib/SimpleSAML/Store/SQL.php
+++ b/lib/SimpleSAML/Store/SQL.php
@@ -231,47 +231,44 @@ class SQL extends Store
                 $query = 'REPLACE INTO '.$table.' '.$colNames.' '.$values;
                 $query = $this->pdo->prepare($query);
                 $query->execute($data);
-                return;
+                break;
             case 'sqlite':
                 $query = 'INSERT OR REPLACE INTO '.$table.' '.$colNames.' '.$values;
                 $query = $this->pdo->prepare($query);
                 $query->execute($data);
-                return;
+                break;
+            default:
+                $updateCols = [];
+                $condCols = [];
+                $condData = [];
+
+                foreach ($data as $col => $value) {
+                    $tmp = $col.' = :'.$col;
+
+                    if (in_array($col, $keys, true)) {
+                        $condCols[] = $tmp;
+                        $condData[$col] = $value;
+                    } else {
+                        $updateCols[] = $tmp;
+                    }
+                }
+
+                $selectQuery = 'SELECT * FROM '.$table.' WHERE '.implode(' AND ', $condCols);
+                $selectQuery = $this->pdo->prepare($selectQuery);
+                $selectQuery->execute($condData);
+
+                if ($selectQuery->rowCount() > 0) {
+                    // Update
+                    $insertOrUpdateQuery = 'UPDATE '.$table.' SET '.implode(',', $updateCols).' WHERE '.implode(' AND ', $condCols);
+                    $insertOrUpdateQuery = $this->pdo->prepare($insertOrUpdateQuery);
+                } else {
+                    // Insert
+                    $insertOrUpdateQuery = 'INSERT INTO '.$table.' '.$colNames.' '.$values;
+                    $insertOrUpdateQuery = $this->pdo->prepare($insertOrUpdateQuery);
+                }
+                $insertOrUpdateQuery->execute($data);
+                break;                
         }
-
-        // default implementation, try INSERT, and UPDATE if that fails.
-        $insertQuery = 'INSERT INTO '.$table.' '.$colNames.' '.$values;
-        $insertQuery = $this->pdo->prepare($insertQuery);
-        try {
-            $insertQuery->execute($data);
-            return;
-        } catch (PDOException $e) {
-            $duplicateInsertErrorCodes = [
-                'pgsql' => '23505',
-                'sqlsrv' => '23000'
-            ];
-
-            if (!array_key_exists($this->driver, $duplicateInsertErrorCodes) || $duplicateInsertErrorCodes[$this->driver] !== (string) $e->getCode()) {
-                Logger::error('Error while saving data: '.$e->getMessage());
-                throw $e;
-            }
-        }
-
-        $updateCols = [];
-        $condCols = [];
-        foreach ($data as $col => $value) {
-            $tmp = $col.' = :'.$col;
-
-            if (in_array($col, $keys, true)) {
-                $condCols[] = $tmp;
-            } else {
-                $updateCols[] = $tmp;
-            }
-        }
-
-        $updateQuery = 'UPDATE '.$table.' SET '.implode(',', $updateCols).' WHERE '.implode(' AND ', $condCols);
-        $updateQuery = $this->pdo->prepare($updateQuery);
-        $updateQuery->execute($data);
     }
 
 
-- 
GitLab