Changeset 23375


Ignore:
Timestamp:
2014/04/29 13:19:40 (6 years ago)
Author:
Seasoft
Message:

#2532 (LC_Page_Admin_Contents_CsvSql#lfDoCsvOutput LIMIT の判定が不適切)
#2531 (DBMS に依存したサブクエリー内の LIMIT OFFSET を排除する)

Location:
branches/version-2_13-dev/data/class
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/version-2_13-dev/data/class/helper/SC_Helper_CSV.php

    r23362 r23375  
    2121    public $arrSubnaviName; 
    2222 
     23    /** ヘッダーを出力するか (cbOutputCSV 用) */ 
     24    private $output_header = false; 
     25 
    2326    /** 
    2427     * デフォルトコンストラクタ. 
     
    208211    public function cbOutputCSV($data) 
    209212    { 
     213        // 1行目のみヘッダーを出力する 
     214        if ($this->output_header) { 
     215            $line = $this->sfArrayToCsv(array_keys($data)); 
     216            $line = mb_convert_encoding($line, 'SJIS-Win'); 
     217            $line .= "\r\n"; 
     218            fwrite($this->fpOutput, $line); 
     219            $this->output_header = false; 
     220        } 
    210221        $line = $this->sfArrayToCsv($data); 
    211222        $line = mb_convert_encoding($line, 'SJIS-Win'); 
     
    222233     * @param  integer $sql         SQL文 
    223234     * @param  array   $arrVal      プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。 
    224      * @param  string  $file_head   ファイル名の頭に付ける文字列 
    225      * @param  array   $arrHeader   ヘッダ出力列配列 
    226      * @param  boolean $is_download true:ダウンロード用出力までさせる false:CSVの内容を返す(旧方式、メモリを食います。) 
     235     * @param  string       ファイル名の頭に付ける文字列 
     236     * @param  array|null   ヘッダ出力列配列。null の場合、SQL 文の列名を出力する。 
     237     * @param  boolean     true:ダウンロード用出力までさせる false:CSVの内容を返す(旧方式、メモリを食います。) 
    227238     * @return mixed   $is_download = true時 成功失敗フラグ(boolean) 、$is_downalod = false時 string 
    228239     */ 
    229     public function sfDownloadCsvFromSql($sql, $arrVal = array(), $file_head = 'csv', $arrHeader = array(), $is_download = false) 
     240    public function sfDownloadCsvFromSql($sql, $arrVal = array(), $file_head = 'csv', $arrHeader = null, $is_download = false) 
    230241    { 
    231242        $objQuery =& SC_Query_Ex::getSingletonInstance(); 
    232243 
    233         // ヘッダ構築 
    234         if (is_array($arrHeader)) { 
    235             $header = $this->sfArrayToCsv($arrHeader); 
    236             $header = mb_convert_encoding($header, 'SJIS-Win'); 
    237             $header .= "\r\n"; 
    238         } 
    239  
    240         //テンポラリファイル作成 
     244        // テンポラリファイル作成 
    241245        // TODO: パフォーマンス向上には、ストリームを使うようにすると良い 
    242246        //  環境要件がPHPバージョン5.1以上になったら使うように変えても良いかと 
     
    244248        $tmp_filename = tempnam(CSV_TEMP_REALDIR, $file_head . '_csv'); 
    245249        $this->fpOutput = fopen($tmp_filename, 'w+'); 
    246         fwrite($this->fpOutput, $header); 
     250        $this->output_header = false; 
     251 
     252        // ヘッダー構築 
     253        if (is_array($arrHeader)) { 
     254            $header = $this->sfArrayToCsv($arrHeader); 
     255            $header = mb_convert_encoding($header, 'SJIS-Win'); 
     256            $header .= "\r\n"; 
     257            fwrite($this->fpOutput, $header); 
     258        } elseif (is_null($arrHeader)) { 
     259            // ループバック内でヘッダーを出力する 
     260            $this->output_header = true; 
     261        } 
     262 
    247263        $objQuery->doCallbackAll(array(&$this, 'cbOutputCSV'), $sql, $arrVal); 
     264 
     265        // コールバック内でヘッダー出力する場合、0行時にヘッダーを生成できない。 
     266        // コールバックが呼ばれていない場合、念のため CRLF を出力しておく。 
     267        // XXX WEB画面前提で、アラート表示する流れのほうが親切かもしれない。 
     268        if ($this->output_header) { 
     269            fwrite($this->fpOutput, "\r\n"); 
     270        } 
    248271 
    249272        fclose($this->fpOutput); 
     
    257280        } 
    258281 
    259         //テンポラリファイル削除 
     282        // テンポラリファイル削除 
    260283        unlink($tmp_filename); 
    261284 
  • branches/version-2_13-dev/data/class/pages/admin/contents/LC_Page_Admin_Contents_CsvSql.php

    r23124 r23375  
    352352    public function lfDoCsvOutput($sql_id) 
    353353    { 
     354        $objCSV = new SC_Helper_CSV_Ex(); 
     355 
    354356        $arrData = $this->lfGetSqlList('sql_id = ?', array($sql_id)); 
    355         $sql = 'SELECT ' . $arrData[0]['csv_sql'] . ' '; 
    356  
    357         // TODO: ヘッダ取得 SQL内にLIMIT文がある場合はLIMIT句は追加しないので重いかも 
    358         $objQuery =& SC_Query_Ex::getSingletonInstance(); 
    359  
    360         $arrHeader = array(); 
    361         if (!preg_match('/ LIMIT /', $sql)) { 
    362             $head_sql = $sql . ' LIMIT 0'; 
    363         } else { 
    364             $head_sql = $sql; 
    365         } 
    366         $arrData = $objQuery->getQueryDefsFields($head_sql, array(), true); 
    367         if (!SC_Utils_Ex::isBlank($arrData)) { 
    368             foreach ($arrData as $key => $val) { 
    369                 $arrHeader[] = $key; 
    370             } 
    371         } 
    372         $objCSV = new SC_Helper_CSV_Ex(); 
    373         $objCSV->sfDownloadCsvFromSql($sql, array(), 'contents', $arrHeader, true); 
     357        $sql = 'SELECT ' . $arrData[0]['csv_sql']; 
     358 
     359        $objCSV->sfDownloadCsvFromSql($sql, array(), 'contents', null, true); 
    374360        SC_Response_Ex::actionExit(); 
    375361    } 
Note: See TracChangeset for help on using the changeset viewer.