public function propPatch($path, PropPatch $propPatch)
    {
        $propPatch->handleRemaining(function ($properties) use ($path) {
            if ('pgsql' === $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                $updateSql = <<<SQL
INSERT INTO {$this->tableName} (path, name, valuetype, value)
VALUES (:path, :name, :valuetype, :value)
ON CONFLICT (path, name)
DO UPDATE SET valuetype = :valuetype, value = :value
SQL;
            } else {
                $updateSql = <<<SQL
REPLACE INTO {$this->tableName} (path, name, valuetype, value)
VALUES (:path, :name, :valuetype, :value)
SQL;
            }

            $updateStmt = $this->pdo->prepare($updateSql);
            $deleteStmt = $this->pdo->prepare('DELETE FROM '.$this->tableName.' WHERE path = ? AND name = ?');

            foreach ($properties as $name => $value) {
                if (!is_null($value)) {
                    if (is_scalar($value)) {
                        $valueType = self::VT_STRING;
                    } elseif ($value instanceof Complex) {
                        $valueType = self::VT_XML;
                        $value = $value->getXml();
                    } else {
                        $valueType = self::VT_OBJECT;
                        $value = serialize($value);
                    }

                    $updateStmt->bindParam('path', $path, \PDO::PARAM_STR);
                    $updateStmt->bindParam('name', $name, \PDO::PARAM_STR);
                    $updateStmt->bindParam('valuetype', $valueType, \PDO::PARAM_INT);
                    $updateStmt->bindParam('value', $value, \PDO::PARAM_LOB);

                    $updateStmt->execute();
                } else {
                    $deleteStmt->execute([$path, $name]);
                }
            }

            return true;
        });
    }