Index: /branches/version-2_12-dev/data/Smarty/templates/admin/system/bkup.tpl
===================================================================
--- /branches/version-2_12-dev/data/Smarty/templates/admin/system/bkup.tpl	(revision 21541)
+++ /branches/version-2_12-dev/data/Smarty/templates/admin/system/bkup.tpl	(revision 21730)
@@ -87,8 +87,8 @@
                     <td ><!--{$arrBkupList[cnt].bkup_memo}--></td>
                     <td align="center"><!--{$arrBkupList[cnt].create_date|sfCutString:19:true:false}--></td>
-                    <td align="center"><a href="#" onclick="fnRestore('<!--{$arrBkupList[cnt].bkup_name}-->'); return false;">リストア</a></td>
-                    <td align="center"><a href="#" onclick="fnModeSubmit('download','list_name','<!--{$arrBkupList[cnt].bkup_name}-->'); return false;">ダウンロード</a></td>
+                    <td align="center"><a href="javascript:;" onclick="fnRestore('<!--{$arrBkupList[cnt].bkup_name}-->'); return false;">リストア</a></td>
+                    <td align="center"><a href="javascript:;" onclick="fnModeSubmit('download','list_name','<!--{$arrBkupList[cnt].bkup_name}-->'); return false;">ダウンロード</a></td>
                     <td align="center">
-                        <a href="#" onclick="fnModeSubmit('delete','list_name','<!--{$arrBkupList[cnt].bkup_name}-->'); return false;">削除</a>
+                        <a href="javascript:;" onclick="fnModeSubmit('delete','list_name','<!--{$arrBkupList[cnt].bkup_name}-->'); return false;">削除</a>
                     </td>
                 </tr>
@@ -97,11 +97,11 @@
     <!--{/if}-->
 
-    <!--{if $restore_msg != ""}-->
+    <!--{if strlen($tpl_restore_msg) >= 1}-->
         <h2>実行結果</h2>
         <div class="message">
-            <!--{if $restore_err == false}-->
-                <div class="btn"><a class="btn-normal" href="javascript:;" name="restore_config" onClick="document.body.style.cursor = 'wait'; form1.mode.value='restore_config'; form1.list_name.value='<!--{$restore_name}-->'; submit(); return false;"><span>テーブル構成を無視してリストアする</span></a></div>
+            <!--{if $tpl_restore_err == false}-->
+                <div class="btn"><a class="btn-normal" href="javascript:;" name="restore_config" onClick="document.body.style.cursor = 'wait'; form1.mode.value='restore_config'; form1.list_name.value='<!--{$tpl_restore_name|h}-->'; submit(); return false;"><span>エラーを無視してリストアする</span></a></div>
             <!--{/if}-->
-            <!--{$restore_msg}-->
+            <!--{$tpl_restore_msg|h}-->
         </div>
     <!--{/if}-->
Index: /branches/version-2_12-dev/data/class/pages/admin/system/LC_Page_Admin_System_Bkup.php
===================================================================
--- /branches/version-2_12-dev/data/class/pages/admin/system/LC_Page_Admin_System_Bkup.php	(revision 21693)
+++ /branches/version-2_12-dev/data/class/pages/admin/system/LC_Page_Admin_System_Bkup.php	(revision 21730)
@@ -34,4 +34,13 @@
 class LC_Page_Admin_System_Bkup extends LC_Page_Admin_Ex {
 
+    /** リストア中にエラーが発生したか */
+    var $tpl_restore_err = false;
+
+    /** 対象外とするシーケンス生成器 */
+    var $arrExcludeSequence = array(
+        'plsql_profiler_runid', // Postgres Plus Advanced Server 9.1
+        'snapshot_num',         // Postgres Plus Advanced Server 9.1
+    );
+
     // }}}
     // {{{ functions
@@ -82,5 +91,6 @@
         $arrForm = array();
 
-        switch ($this->getMode()) {
+        $this->mode = $this->getMode();
+        switch ($this->mode) {
 
             // バックアップを作成する
@@ -93,5 +103,5 @@
                 if (SC_Utils_Ex::isBlank($arrErrTmp[1])) {
                     // データ型以外のエラーチェック
-                    $arrErrTmp[2] = $this->lfCheckError($objFormParam->getHashArray(), $this->getMode());
+                    $arrErrTmp[2] = $this->lfCheckError($objFormParam->getHashArray(), $this->mode);
                 }
 
@@ -131,14 +141,22 @@
             // リストア
             case 'restore_config':
-                $this->mode = 'restore_config';
-
             case 'restore':
                 // データベースに存在するかどうかチェック
-                $arrErr = $this->lfCheckError($objFormParam->getHashArray(), $this->getMode());
+                $arrErr = $this->lfCheckError($objFormParam->getHashArray(), $this->mode);
 
                 // エラーがなければリストア処理を行う
                 if (SC_Utils_Ex::isBlank($arrErr)) {
                     $arrData = $objFormParam->getHashArray();
-                    $this->lfRestore($arrData['list_name'], $this->bkup_dir, $this->bkup_ext, $this->mode);
+
+                    $msg = '「' . $arrData['list_name'] . '」のリストアを開始します。';
+                    GC_Utils_Ex::gfPrintLog($msg);
+
+                    $success = $this->lfRestore($arrData['list_name'], $this->bkup_dir, $this->bkup_ext, $this->mode);
+
+                    $msg = '「' . $arrData['list_name'] . '」の';
+                    $msg .= $success ? 'リストアを終了しました。' : 'リストアに失敗しました。';
+
+                    $this->tpl_restore_msg .= $msg . "\n";
+                    GC_Utils_Ex::gfPrintLog($msg);
                 }
                 break;
@@ -148,5 +166,5 @@
 
                 // データベースに存在するかどうかチェック
-                $arrErr = $this->lfCheckError($objFormParam->getHashArray(), $this->getMode());
+                $arrErr = $this->lfCheckError($objFormParam->getHashArray(), $this->mode);
 
                 // エラーがなければリストア処理を行う
@@ -165,5 +183,5 @@
 
                 // データベースに存在するかどうかチェック
-                $arrErr = $this->lfCheckError($objFormParam->getHashArray(), $this->getMode());
+                $arrErr = $this->lfCheckError($objFormParam->getHashArray(), $this->mode);
 
                 // エラーがなければダウンロード処理を行う
@@ -238,9 +256,7 @@
     function lfCheckError(&$arrForm, $mode) {
 
-        $arrVal = array();
-
         switch ($mode) {
             case 'bkup':
-                $arrVal[] = $arrForm['bkup_name'];
+                $name = $arrForm['bkup_name'];
                 break;
 
@@ -249,13 +265,14 @@
             case 'download':
             case 'delete':
-                $arrVal[] = $arrForm['list_name'];
+                $name = $arrForm['list_name'];
                 break;
 
             default:
+                trigger_error('不明な処理', E_USER_ERROR);
                 break;
         }
 
         // 重複・存在チェック
-        $ret = $this->lfGetBkupData('WHERE bkup_name = ?', $arrVal);
+        $ret = $this->lfGetBkupData('', $name);
         if (count($ret) > 0 && $mode == 'bkup') {
             $arrErr['bkup_name'] = 'バックアップ名が重複しています。別名を入力してください。';
@@ -382,8 +399,14 @@
         $arrSequences = $objQuery->listSequences();
 
-        foreach ($arrSequences as $val) {
-            $seq = $objQuery->currVal($val);
-
-            $ret .= $val . ',';
+        foreach ($arrSequences as $name) {
+            if (in_array($name, $this->arrExcludeSequence, true)) {
+                continue 1;
+            }
+
+            // XXX SC_Query::currVal は、PostgreSQL で nextval と等しい値を戻すケースがある。欠番を生じうるが、さして問題無いと推測している。
+            $seq = $objQuery->currVal($name);
+
+            // TODO CSV 生成の共通処理を使う
+            $ret .= $name . ',';
             $ret .= is_null($seq) ? '0' : $seq;
             $ret .= "\r\n";
@@ -404,14 +427,47 @@
     }
 
-    // バックアップテーブルからデータを取得する
-    function lfGetBkupData($where = '', $data = array()) {
+    /**
+     * バックアップの一覧を取得する
+     */
+    function lfGetBkupData($sql_option = '', $filter_bkup_name) {
         $objQuery =& SC_Query_Ex::getSingletonInstance();
 
-        $sql = 'SELECT bkup_name, bkup_memo, create_date FROM dtb_bkup ';
-        if ($where != '') {
-            $sql .= $where;
-        }
-
-        $ret = $objQuery->getAll($sql,$data);
+        // テーブルから取得
+        $arrVal = array();
+
+        $sql = 'SELECT bkup_name, bkup_memo, create_date FROM dtb_bkup';
+        if (strlen($filter_bkup_name) >= 1) {
+            $sql .= ' WHERE bkup_name = ?';
+            $arrVal[] = $filter_bkup_name;
+        }
+        if ($sql_option != '') {
+            $sql .= ' ' . $sql_option;
+        }
+
+        $ret = $objQuery->getAll($sql, $arrVal);
+
+        // ファイルのみのものを取得
+        $glob = glob($this->bkup_dir . '*' . $this->bkup_ext);
+        if (is_array($glob)) {
+            foreach ($glob as $path) {
+                $bkup_name = basename($path, $this->bkup_ext);
+                if (strlen($filter_bkup_name) >= 1 && $bkup_name !== $filter_bkup_name) {
+                    continue 1;
+                }
+                unset($row);
+                foreach (array_keys($ret) as $key) {
+                    if ($ret[$key]['bkup_name'] == $bkup_name) {
+                        $row =& $ret[$key];
+                    }
+                }
+                if (!isset($row)) {
+                    $ret[] = array();
+                    $row =& $ret[array_pop(array_keys($ret))];
+                    $row['bkup_name'] = $bkup_name;
+                    $row['bkup_memo'] = '(記録なし。バックアップファイルのみ。)';
+                    $row['create_date'] = date("Y-m-d H:i:s", filemtime($path));
+                }
+            }
+        }
 
         return $ret;
@@ -455,21 +511,19 @@
         $success = $this->lfExeInsertSQL($objQuery, $work_dir, $mode);
 
-        // 自動採番の値をセット
-        if ($success) $this->lfSetAutoInc($objQuery, $work_dir . 'autoinc_data.csv');
+        // シーケンス生成器を復元する
+        if ($success) $this->restoreSequence($objQuery, $work_dir . 'autoinc_data.csv');
 
         // リストア成功ならコミット失敗ならロールバック
         if ($success) {
             $objQuery->commit();
-            $this->restore_msg = 'リストア終了しました。';
-            $this->restore_err = true;
+            $this->tpl_restore_err = true;
         } else {
             $objQuery->rollback();
-            $this->restore_msg = 'リストアに失敗しました。';
-            $this->restore_name = $bkup_name;
-            $this->restore_err = false;
-        }
-        GC_Utils_Ex::gfPrintLog($this->restore_msg);
+            $this->tpl_restore_name = $bkup_name;
+        }
 
         // FIXME この辺りで、バックアップ時と同等の一時ファイルの削除を実行すべきでは?
+
+        return $success;
     }
 
@@ -521,5 +575,5 @@
             while (!feof($fp)) {
                 $line++;
-                $arrCsvLine = fgetcsv($fp, 1000000);
+                $arrCsvLine = fgetcsv($fp, 1024 * 1024);
 
                 // 1行目: 列名
@@ -548,13 +602,22 @@
     }
 
-    // 自動採番をセット
-    function lfSetAutoInc(&$objQuery, $csv) {
+    /**
+     * シーケンス生成器を復元する
+     */
+    function restoreSequence(&$objQuery, $csv) {
         // csvファイルからデータの取得
         $arrCsvData = file($csv);
 
-        foreach ($arrCsvData as $val) {
-            $arrData = explode(',', trim($val));
-
-            $objQuery->setval($arrData[0], $arrData[1]);
+        foreach ($arrCsvData as $line) {
+            list($name, $currval) = explode(',', trim($line));
+
+            if (in_array($name, $this->arrExcludeSequence, true)) {
+                continue 1;
+            }
+
+            // FIXME テーブルと同様に整合チェックを行う。また不整合時はスキップして続行する。
+
+            // XXX +1 ではなく、nextVal を呼ぶべきかも。
+            $objQuery->setVal($name, $currval + 1);
         }
     }
