blobstore.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:21k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: blobstore.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 19:23:15  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.5
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: blobstore.cpp,v 1000.0 2004/06/01 19:23:15 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE                          
  13.  *               National Center for Biotechnology Information
  14.  *                                                                          
  15.  *  This software/database is a "United States Government Work" under the   
  16.  *  terms of the United States Copyright Act.  It was written as part of    
  17.  *  the author's official duties as a United States Government employee and 
  18.  *  thus cannot be copyrighted.  This software/database is freely available 
  19.  *  to the public for use. The National Library of Medicine and the U.S.    
  20.  *  Government have not placed any restriction on its use or reproduction.  
  21.  *                                                                          
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy  
  23.  *  and reliability of the software and data, the NLM and the U.S.          
  24.  *  Government do not and cannot warrant the performance or results that    
  25.  *  may be obtained by using this software or data. The NLM and the U.S.    
  26.  *  Government disclaim all warranties, express or implied, including       
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.                                                                
  29.  *                                                                          
  30.  *  Please cite the author in any work or product based on this material.   
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Vladimir Soussov
  35.  *
  36.  */
  37. #include <ncbi_pch.hpp>
  38. #include <util/rwstream.hpp>
  39. #include <util/compress/stream.hpp>
  40. #include <util/compress/zlib.hpp>
  41. #include <util/compress/bzip2.hpp>
  42. #include <dbapi/driver/exception.hpp>
  43. #include <dbapi/driver/driver_mgr.hpp>
  44. #include <dbapi/driver/util/blobstore.hpp>
  45. USING_NCBI_SCOPE;
  46. bool CBlobWriter::storeBlob(void)
  47. {
  48.     try {
  49.         m_Con->SendData(m_dMaker->ItDescriptor(), m_Blob, m_LogIt);
  50.         m_Blob.Truncate();
  51.         return true;
  52.     }
  53.     catch (CDB_Exception& e) {
  54.         CDB_UserHandler_Stream myExHandler(&cerr);
  55.         
  56.         myExHandler.HandleIt(&e);
  57.         return false;
  58.     }
  59. }
  60. CBlobWriter::CBlobWriter(CDB_Connection* con, ItDescriptorMaker* d_maker, 
  61.                          size_t image_limit, TFlags flags)
  62. {
  63.     m_Con= con;
  64.     m_dMaker= d_maker;
  65.     m_Limit= (image_limit > 1)? image_limit : (16*1024*1024);
  66.     m_LogIt= ((flags & fLogBlobs) != 0);
  67.     m_DelDesc= ((flags & fOwnCon) != 0);
  68.     m_DelCon=  ((flags & fOwnCon) != 0);
  69. }
  70. ERW_Result CBlobWriter::Write(const void* buf,
  71.                               size_t      count,
  72.                               size_t*     bytes_written)
  73. {
  74.     size_t n= m_Blob.Append(buf, count);
  75.     if(bytes_written) *bytes_written= n;
  76.     if(m_Blob.Size() > m_Limit) {
  77.         // blob is off limit
  78.         if(!storeBlob()) return eRW_Error;
  79.     }
  80.     return eRW_Success;
  81. }
  82. ERW_Result CBlobWriter::Flush(void)
  83. {
  84.     if(m_Blob.Size() > 0) {
  85.         if(!storeBlob()) return eRW_Error;
  86.     }
  87.     return eRW_Success;
  88. }
  89. CBlobWriter::~CBlobWriter()
  90. {
  91.     Flush();
  92.     if(m_DelDesc) {
  93.         m_dMaker->Fini();
  94.         delete m_dMaker;
  95.     }
  96.     if(m_DelCon) {
  97.         delete m_Con;
  98.     }
  99. }
  100. ERW_Result CBlobReader::Read(void* buf, size_t count, size_t* bytes_read)
  101. {
  102.     size_t n= 0;
  103.     size_t rn= 0;
  104.     ERW_Result r= eRW_Success;
  105.     if(m_AllDone) {
  106.         r= eRW_Eof;
  107.     }
  108.     else try {
  109.         bool isNull;
  110.         do {
  111.             n= m_Res->ReadItem(buf, count, &isNull);
  112.             if(n >= count) { // we did all we need
  113.                 if(bytes_read) *bytes_read= rn+n;
  114.                 return r;
  115.             }
  116.             // need to read the tail from other items
  117.             rn+= n;
  118.             count-= n;
  119.             buf= ((char*)buf)+n;
  120.             n= 0;
  121.             if(m_ItemNum == m_Res->CurrentItemNo()) {
  122.                 // we should not be here, but just in case
  123.                 if(!m_Res->SkipItem()) m_ItemNum= -1;
  124.                 else ++m_ItemNum;
  125.             }
  126.             else m_ItemNum= m_Res->CurrentItemNo();
  127.             if((m_ItemNum < 0 || 
  128.                 (unsigned int)m_ItemNum >= m_Res->NofItems()) && 
  129.                m_Res->Fetch()) {
  130.                 m_ItemNum= 0; // starting next row
  131.             }
  132.         }
  133.         while(m_ItemNum >= 0 && 
  134.               (unsigned int)m_ItemNum < m_Res->NofItems());
  135.         m_AllDone= true; // nothing to read any more
  136.     } catch (CDB_Exception& e) {
  137.         m_AllDone= true;
  138.     }
  139.     
  140.     if(bytes_read) *bytes_read= n + rn;
  141.     return r;
  142. }
  143. ERW_Result CBlobReader::PendingCount(size_t* count)
  144. {
  145.     if(count) *count= 0;
  146.     return m_AllDone? eRW_Eof : eRW_NotImplemented;
  147. }
  148. CBlobReader::~CBlobReader()
  149. {
  150.     if(m_Cmd) {
  151.         delete m_Res;
  152.         delete m_Cmd;
  153.     }
  154.     if(m_Con) {
  155.         delete m_Con;
  156.     }
  157. }
  158. CBlobRetriever::CBlobRetriever(I_DriverContext* pCntxt,
  159.                                const string& server,
  160.                                const string& user,
  161.                                const string& passwd,
  162.                                const string& query)
  163. {
  164.     m_Conn= 0;
  165.     m_Cmd= 0;
  166.     m_Res= 0;
  167.     try {
  168.         m_Conn= pCntxt->Connect(server, user, passwd, 0, true);
  169.         m_Cmd= m_Conn->LangCmd(query);
  170.         m_Cmd->Send();
  171.         while(m_Cmd->HasMoreResults()) {
  172.             m_Res=m_Cmd->Result();
  173.             if(!m_Res) continue;
  174.             if(m_Res->ResultType() != eDB_RowResult) {
  175.                 delete m_Res;
  176.                 continue;
  177.             }
  178.             if(m_Res->Fetch()) {
  179.                 m_IsGood= true;
  180.                 return;
  181.             } 
  182.         }
  183.     } catch (CDB_Exception& e) {
  184.         CDB_UserHandler_Stream myExHandler(&cerr);
  185.         
  186.         myExHandler.HandleIt(&e);
  187.     }
  188.     m_IsGood= false;
  189. }
  190.     
  191. bool CBlobRetriever::Dump(ostream& s, ECompressMethod cm)
  192. {
  193.     if(m_IsGood) {
  194.         CBlobReader* bReader= new CBlobReader(m_Res);
  195.         CRStream* iStream= new CRStream(bReader);
  196.         CCompressionStreamProcessor* zProc;
  197.         switch(cm) {
  198.         case eZLib:
  199.             zProc= new CCompressionStreamProcessor((CZipDecompressor*)(new CZipDecompressor), 
  200.                                                    CCompressionStreamProcessor::eDelete);
  201.             break;
  202.         case eBZLib:
  203.             zProc=  new CCompressionStreamProcessor((CBZip2Decompressor*)(new CBZip2Decompressor), 
  204.                                                     CCompressionStreamProcessor::eDelete);
  205.             break;
  206.         default:
  207.             zProc= 0;
  208.         }
  209.         if(zProc) {
  210.             CCompressionIStream* zStream= new CCompressionIStream(*iStream, zProc);
  211.             s << zStream->rdbuf();
  212.             delete zStream;
  213.             delete zProc;
  214.         }
  215.         else {
  216.             s << iStream->rdbuf();
  217.         }
  218.         delete iStream;
  219.         delete bReader;
  220.         m_IsGood= m_Res->Fetch();
  221.         return true;
  222.     }
  223.     return false;
  224. }
  225. CBlobRetriever::~CBlobRetriever()
  226. {
  227.     if(m_Res) delete m_Res;
  228.     if(m_Cmd) delete m_Cmd;
  229.     if(m_Conn) delete m_Conn;
  230. }
  231. CBlobLoader::CBlobLoader(I_DriverContext* pCntxt,
  232.                          const string&    server, 
  233.                          const string&    user,
  234.                          const string&    passwd,
  235.                          ItDescriptorMaker* d_maker)
  236. {
  237.     m_Conn= 0;
  238.     try {
  239.         m_Conn= pCntxt->Connect(server, user, passwd, 0, true);
  240.         m_dMaker= d_maker;
  241.         m_IsGood= true;
  242.         return;
  243.     } catch (CDB_Exception& e) {
  244.         CDB_UserHandler_Stream myExHandler(&cerr);
  245.         
  246.         myExHandler.HandleIt(&e);
  247.     }
  248.     m_IsGood= false;    
  249. }
  250. bool CBlobLoader::Load(istream& s, ECompressMethod cm, size_t image_limit, bool log_it)
  251. {
  252.     if(m_IsGood && m_dMaker->Init(m_Conn)) {
  253.         CBlobWriter* bWriter= new CBlobWriter(m_Conn, m_dMaker, image_limit, log_it);
  254.         CWStream* oStream= new CWStream(bWriter);
  255.         CCompressionStreamProcessor* zProc;
  256.         switch(cm) {
  257.         case eZLib:
  258.             zProc= new CCompressionStreamProcessor((CZipCompressor*)(new CZipCompressor), 
  259.                                                    CCompressionStreamProcessor::eDelete);
  260.             break;
  261.         case eBZLib:
  262.             zProc=  new CCompressionStreamProcessor((CBZip2Compressor*)(new CBZip2Compressor), 
  263.                                                     CCompressionStreamProcessor::eDelete);
  264.             break;
  265.         default:
  266.             zProc= 0;
  267.         }
  268.         if(zProc) {
  269.             CCompressionOStream* zStream= new CCompressionOStream(*oStream, zProc);
  270.             *zStream << s.rdbuf();
  271.             delete zStream;
  272.             delete zProc;
  273.         }
  274.         else {
  275.             *oStream << s.rdbuf();
  276.         }
  277.         delete oStream;
  278.         delete bWriter;
  279.         return m_dMaker->Fini();
  280.     }
  281.     return false;
  282.     
  283. }
  284. CSimpleBlobStore::CSimpleBlobStore(const string& table_name,
  285.                                   const string& key_col_name,
  286.                                   const string& num_col_name,
  287.                                    const string blob_column[],
  288.                                    bool is_text) :
  289.     m_TableName(table_name), m_KeyColName(key_col_name), 
  290.     m_NumColName(num_col_name), m_Desc(table_name)
  291. {
  292.     m_Con= 0;
  293.     m_Cmd= 0;
  294.     for(m_nofDataCols= 0; !blob_column[m_nofDataCols].empty(); m_nofDataCols++);
  295.     if(m_nofDataCols) {
  296.         int i;
  297.         string init_val(is_text? "' '" : "0x0");
  298.         m_DataColName= new string[m_nofDataCols];
  299.         for(i= 0; i < m_nofDataCols; i++) {
  300.             m_DataColName[i]= blob_column[i];
  301.         }
  302.         m_sCMD= "if exists(select * from " + m_TableName +
  303.             " where " + m_KeyColName + " = @key AND " + m_NumColName +
  304.             " = @n) update " + m_TableName + " set";
  305.         for(i= 0; i < m_nofDataCols; i++) {
  306.             m_sCMD+= (i? ", ":" ") + m_DataColName[i] + "=" + init_val;
  307.         }
  308.         m_sCMD+= " where " + m_KeyColName + " = @key AND " + m_NumColName +
  309.             " = @n else insert " + m_TableName + "(" + m_KeyColName + "," +
  310.             m_NumColName;
  311.         for(i= 0; i < m_nofDataCols; i++) {
  312.             m_sCMD+= ", " + m_DataColName[i];
  313.         }
  314.         m_sCMD+= ")values(@key,@n";
  315.         for(i= 0; i < m_nofDataCols; i++) {
  316.             m_sCMD+= "," + init_val;
  317.         }
  318.         m_sCMD+=")";
  319.     }
  320.     else m_DataColName= 0;
  321. }
  322. CSimpleBlobStore::~CSimpleBlobStore()
  323. {
  324.     if(m_DataColName) delete[]m_DataColName;
  325.     if(m_Cmd) delete m_Cmd;
  326. }
  327. bool CSimpleBlobStore::Init(CDB_Connection* con)
  328. {
  329.     m_Con= con;
  330.     m_ImageNum= 0;
  331.     if(m_Key.IsNULL() || (m_nofDataCols < 1)) return false;
  332.     m_Cmd= m_Con->LangCmd(m_sCMD, 2);
  333.     m_Cmd->SetParam("@key", &m_Key);
  334.     m_Cmd->BindParam("@n", &m_RowNum);
  335.     return true;
  336. }
  337. /*
  338. if exists(select key from T where key= @key and n = @n)
  339. begin
  340.    update T set b1=0x0, ... bn= 0x0 where key= @key and n= @n
  341. end
  342. else
  343.    insert T(key, n, b1, ...,bn) values(@key, @n, 0x0, ...,0x0)
  344. */
  345. I_ITDescriptor& CSimpleBlobStore::ItDescriptor(void)
  346. {
  347.     m_RowNum= (Int4)(m_ImageNum / m_nofDataCols);
  348.     int i= m_ImageNum % m_nofDataCols;
  349.     if(i == 0) { // prepare new row
  350.         m_Cmd->Send(); // sending command to update/insert row
  351.         m_Cmd->DumpResults(); // we don't expect any useful results
  352.         string s= m_KeyColName + "= '";
  353.         s.append(m_Key.Value());
  354.         s+= "' AND " + m_NumColName + "=";
  355.         char buf[32];
  356.         sprintf(buf, "%ld", (long) m_RowNum.Value());
  357.         s.append(buf);
  358.             
  359.         m_Desc.SetSearchConditions(s);
  360.     }
  361.     m_Desc.SetColumn(m_DataColName[i]);
  362.     m_ImageNum++;
  363.     return m_Desc;
  364. }
  365. bool CSimpleBlobStore::Fini(void)
  366. {
  367.     if(m_nofDataCols > 0) {
  368.         delete m_Cmd;
  369.         int i= m_ImageNum % m_nofDataCols;
  370.         if(i) { // we need to clean-up the current row
  371.             string s= "update " + m_TableName + " set";
  372.             for(int j= i; j < m_nofDataCols; j++) {
  373.                 s+= ((i != j)? ", ":" ") + m_DataColName[j] + " = NULL";
  374.             }
  375.             s+= " where " + m_KeyColName + " = @key AND " + m_NumColName + 
  376.                 " = @n delete " + m_TableName + " where " + m_KeyColName + 
  377.                 " = @key AND " + m_NumColName + " > @n";
  378.             m_Cmd= m_Con->LangCmd(s, 2);
  379.         }
  380.         else {
  381.             string s= "delete " + m_TableName + " where " + m_KeyColName + 
  382.                 " = @key AND " + m_NumColName + " > @n";
  383.             m_Cmd= m_Con->LangCmd(s, 2);
  384.         }
  385.         m_Cmd->SetParam("@key", &m_Key);
  386.         m_Cmd->BindParam("@n", &m_RowNum);
  387.         m_Cmd->Send(); // sending command
  388.         m_Cmd->DumpResults(); // we don't expect any useful results
  389.         delete m_Cmd;
  390.         m_Cmd= 0;
  391.         return true;
  392.     }
  393.     return false;
  394. }
  395. /***************************************************************************************
  396.  * CBlobStore - the simple interface to deal with reading and writing the image/text data
  397.  * from a C++ application
  398.  */
  399. CBlobStore::CBlobStore(I_DriverContext* pCntxt,
  400.                        const string& server, 
  401.                        const string& user,
  402.                        const string& passwd,
  403.                        const string& table_name,
  404.                        ECompressMethod cm, 
  405.                        size_t image_limit, 
  406.                        bool log_it):
  407.     m_Cntxt(pCntxt), m_Server(server), m_User(user), m_Passwd(passwd), m_Table(table_name),
  408.     m_Cm(cm), m_Limit(image_limit), m_LogIt(log_it), m_Pool(server+user+table_name)
  409. {
  410.     if(!m_Cntxt) {
  411.         throw CDB_ClientEx(eDB_Error, 1000010, "CBlobStore", 
  412.                            "Null pointer to driver context");
  413.     }
  414.     CDB_Connection* con= m_Cntxt->Connect(m_Server, m_User, m_Passwd, 0, true, m_Pool);
  415.     if(!con) {
  416.         throw CDB_ClientEx(eDB_Error, 1000020, "CBlobStore",
  417.                            "Can not open connection to SQL server");
  418.     }
  419.     /* derive information regarding the table */
  420.     CDB_LangCmd* lcmd= con->LangCmd("select * from "+m_Table+" where 1=0");
  421.     if(!lcmd->Send()) {
  422.         throw CDB_ClientEx(eDB_Error, 1000030, "CBlobStore",
  423.                            "Failed to send a command to the server");
  424.     }
  425.     m_NofBC= 0;
  426.     m_KeyColName= kEmptyStr;
  427.     m_NumColName= kEmptyStr;
  428.     m_ReadQuery= kEmptyStr;
  429.     m_IsText= false;
  430.     unsigned int n;
  431.     while(lcmd->HasMoreResults()) {
  432.         CDB_Result* r= lcmd->Result();
  433.         if(!r) continue;
  434.         if(r->ResultType() == eDB_RowResult) {
  435.             n= r->NofItems();
  436.             if(n < 2) {
  437.                 delete r;
  438.                 continue;
  439.             }
  440.             m_BlobColumn= new string[n];
  441.             for(unsigned int j= 0; j < n; j++) {
  442.                 switch (r->ItemDataType(j)) {
  443.                 case eDB_VarChar:
  444.                 case eDB_Char:
  445.                 case eDB_LongChar: 
  446.                     m_KeyColName= r->ItemName(j);
  447.                     break;
  448.                 case eDB_Int:
  449.                 case eDB_SmallInt:
  450.                 case eDB_TinyInt:
  451.                 case eDB_BigInt:
  452.                     m_NumColName= r->ItemName(j);
  453.                     break;
  454.                 case eDB_Text: m_IsText= true;
  455.                 case eDB_Image:
  456.                     m_BlobColumn[m_NofBC++]= r->ItemName(j);
  457.                 }
  458.             }
  459.             m_BlobColumn[m_NofBC]= kEmptyStr;
  460.             while(r->Fetch());
  461.         }
  462.         delete r;
  463.     }
  464.     delete lcmd;
  465.     delete con;
  466.     if((m_NofBC < 1) || m_KeyColName.empty()) {
  467.         throw CDB_ClientEx(eDB_Error, 1000040, "CBlobStore",
  468.                            "Table "+m_Table+" can not be used for BlobStore");
  469.     }
  470. }
  471. bool CBlobStore::Exists(const string& blob_id)
  472. {
  473.     CDB_Connection* con= m_Cntxt->Connect(m_Server, m_User, m_Passwd, 0, true, m_Pool);
  474.     if(!con) {
  475.         throw CDB_ClientEx(eDB_Error, 1000020, "CBlobStore::Exists",
  476.                            "Can not open connection to SQL server");
  477.     }
  478.     /* check the key */
  479.     CDB_LangCmd* lcmd= con->LangCmd("if EXISTS(select * from "+m_Table+" where "+
  480.                                     m_KeyColName+"='"+blob_id+"') select 1");
  481.     if(!lcmd->Send()) {
  482.         delete lcmd;
  483.         delete con;
  484.         throw CDB_ClientEx(eDB_Error, 1000030, "CBlobStore::Exists",
  485.                            "Failed to send a command to the server");
  486.     }
  487.     bool re= false;
  488.     while(lcmd->HasMoreResults()) {
  489.         CDB_Result* r= lcmd->Result();
  490.         if(!r) continue;
  491.         if(r->ResultType() == eDB_RowResult) {
  492.             while(r->Fetch())
  493.                 re= true;
  494.         }
  495.         delete r;
  496.     }
  497.     delete lcmd;
  498.     delete con;
  499.     return re;
  500. }
  501. void CBlobStore::Delete(const string& blob_id)
  502. {
  503.     CDB_Connection* con= m_Cntxt->Connect(m_Server, m_User, m_Passwd, 0, true, m_Pool);
  504.     if(!con) {
  505.         throw CDB_ClientEx(eDB_Error, 1000020, "CBlobStore::Delete",
  506.                            "Can not open connection to SQL server");
  507.     }
  508.     /* check the key */
  509.     CDB_LangCmd* lcmd= con->LangCmd("delete "+m_Table+" where "+
  510.                                     m_KeyColName+"='"+blob_id+"'");
  511.     if(!lcmd->Send()) {
  512.         delete lcmd;
  513.         delete con;
  514.         throw CDB_ClientEx(eDB_Error, 1000030, "CBlobStore::delete",
  515.                            "Failed to send a command to the server");
  516.     }
  517.     lcmd->DumpResults();
  518.     delete lcmd;
  519.     delete con;
  520. }
  521. istream* CBlobStore::OpenForRead(const string& blob_id)
  522. {
  523.     CDB_Connection* con= m_Cntxt->Connect(m_Server, m_User, m_Passwd, 0, true, m_Pool);
  524.     if(!con) {
  525.         throw CDB_ClientEx(eDB_Error, 1000020, "CBlobStore::OpenForRead",
  526.                            "Can not open connection to SQL server");
  527.     }
  528.     if(m_ReadQuery.empty()) {
  529.         m_ReadQuery= "set TEXTSIZE 2147483647 select ";
  530.         for(int i= 0; i < m_NofBC; i++) {
  531.             if(i) m_ReadQuery+= ", ";
  532.             m_ReadQuery+= m_BlobColumn[i];
  533.         }
  534.         m_ReadQuery+= " from " + m_Table + " where " + m_KeyColName + "=@blob_id";
  535.         if(!m_NumColName.empty()) {
  536.             m_ReadQuery+= " order by " + m_NumColName + " ASC";
  537.         }
  538.     }
  539.     CDB_LangCmd* lcmd= con->LangCmd(m_ReadQuery, 1);
  540.     CDB_VarChar blob_key(blob_id);
  541.     lcmd->BindParam("@blob_id", &blob_key);
  542.     if(!lcmd->Send()) {
  543.         delete lcmd;
  544.         delete con;
  545.         throw CDB_ClientEx(eDB_Error, 1000030, "CBlobStore::OpenForRead",
  546.                            "Failed to send a command to the server");
  547.     }
  548.     
  549.     while(lcmd->HasMoreResults()) {
  550.         CDB_Result* r= lcmd->Result();
  551.         if(!r) continue;
  552.         if(r->ResultType() != eDB_RowResult) {
  553.             delete r;
  554.             continue;
  555.         }
  556.         if(r->Fetch()) {
  557.             // creating a stream
  558.             CBlobReader* bReader= new CBlobReader(r, lcmd, con);
  559.             CRStream* iStream= new CRStream(bReader, 0, 0, CRWStreambuf::fOwnReader);
  560.             CCompressionStreamProcessor* zProc;
  561.             switch(m_Cm) {
  562.                 
  563.             case eZLib:
  564.                 zProc= new CCompressionStreamProcessor((CZipDecompressor*)(new CZipDecompressor), 
  565.                                                        CCompressionStreamProcessor::eDelete);
  566.                 break;
  567.             case eBZLib:
  568.                 zProc=  new CCompressionStreamProcessor((CBZip2Decompressor*)(new CBZip2Decompressor), 
  569.                                                         CCompressionStreamProcessor::eDelete);
  570.                 break;
  571.             default:
  572.                 return iStream;
  573.             }
  574.             CCompressionIStream* zStream= new CCompressionIStream(*iStream, zProc, 
  575.                                                                   CCompressionStream::fOwnAll);
  576.             
  577.             return zStream;
  578.         } 
  579.     }
  580.     delete lcmd;
  581.     delete con;
  582.     return 0;
  583. }
  584. ostream* CBlobStore::OpenForWrite(const string& blob_id)
  585. {
  586.     CDB_Connection* con= m_Cntxt->Connect(m_Server, m_User, m_Passwd, 0, true, m_Pool);
  587.     if(!con) {
  588.         throw CDB_ClientEx(eDB_Error, 1000020, "CBlobStore::OpenForWrite",
  589.                            "Can not open connection to SQL server");
  590.     }
  591.     CSimpleBlobStore* sbs= new CSimpleBlobStore(m_Table, m_KeyColName, m_NumColName, m_BlobColumn,
  592.                                                 m_IsText);
  593.     sbs->SetKey(blob_id);
  594.     // CBlobLoader* bload= new CBlobLoader(my_context, server_name, user_name, passwd, &sbs);
  595.     if(sbs->Init(con)) {
  596.         CBlobWriter* bWriter= new CBlobWriter(con, sbs, m_Limit, 
  597.                                               CBlobWriter::fOwnAll | (m_LogIt? CBlobWriter::fLogBlobs : 0));
  598.         CWStream* oStream= new CWStream(bWriter, 0, 0,  CRWStreambuf::fOwnWriter);
  599.         CCompressionStreamProcessor* zProc;
  600.         switch(m_Cm) {
  601.         case eZLib:
  602.             zProc= new CCompressionStreamProcessor((CZipCompressor*)(new CZipCompressor), 
  603.                                                    CCompressionStreamProcessor::eDelete);
  604.             break;
  605.         case eBZLib:
  606.             zProc=  new CCompressionStreamProcessor((CBZip2Compressor*)(new CBZip2Compressor), 
  607.                                                     CCompressionStreamProcessor::eDelete);
  608.             break;
  609.         default:
  610.             return oStream;
  611.         }
  612.         CCompressionOStream* zStream= new CCompressionOStream(*oStream, zProc, CCompressionStream::fOwnAll);
  613.         return zStream;
  614.     }
  615.     return 0;
  616. }