sqlite_table.cpp

来自「ncbi源码」· C++ 代码 · 共 450 行

CPP
450
字号
/* * =========================================================================== * PRODUCTION $Log: sqlite_table.cpp,v $ * PRODUCTION Revision 1000.1  2004/06/01 19:42:49  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3 * PRODUCTION * =========================================================================== *//*  $Id: sqlite_table.cpp,v 1000.1 2004/06/01 19:42:49 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Authors:  Mike DiCuccio * * File Description: * */#include <ncbi_pch.hpp>#include <objtools/data_loaders/table/sqlite_table.hpp>#include <sqlite/sqlite.hpp>#include <corelib/ncbifile.hpp>BEGIN_NCBI_SCOPEUSING_SCOPE(objects);//// class CSQliteTableIterator is private - no external class can refer to// this class directly//class CSQLiteTableIterator : public ITableIterator{public:    CSQLiteTableIterator(CSQLiteQuery& q)        : m_Query(&q)    {        Next();    }    // retrieve the current row's data    void GetRow(list<string>& data) const    {        data = m_ThisRow;    }    // advance to the next row    void Next(void)    {        int count = 0;        const char** data = NULL;        const char** cols = NULL;        if ( !m_Query->NextRow(count, data, cols) ) {            m_Query.Reset();        }        m_ThisRow.clear();        if (data  &&  count) {            // remember that our data contains the row_idx            // as the first entry!            for (int i = 1;  i < count;  ++i) {                m_ThisRow.push_back(data[i]);            }        }    }    // check to see if the current iterator is valid    bool IsValid(void) const    {        return m_Query;    }private:    CRef<CSQLiteQuery> m_Query;    list<string> m_ThisRow;};CSQLiteTable::CSQLiteTable(const string& input_file,                           const string& temp_file,                           bool delete_file)    : m_NumRows(0),      m_DeleteFile(delete_file),      m_FileName(input_file),      m_TmpFileName(temp_file){    //    // first, see if our temporary file is already a SQLite DB    //    CFile file(temp_file);    if (file.Exists()) {        try {            m_Sqlite.Reset(new CSQLite(temp_file, false));            //            // retrieve our columns            //            CRef<CSQLiteQuery> q                (m_Sqlite->Compile("select col, name from TableCols"));            int count;            const char** data = NULL;            const char** cols = NULL;            while (q.GetPointer()  &&  q->NextRow(count, data, cols)) {                string col(data[0]);                string str(data[1]);                string::size_type pos = 0;                while ( (pos = str.find_first_of("'", pos)) != string::npos) {                    if (pos  &&  str[pos-1] == '\\') {                        str.erase(pos - 1, 1);                        --pos;                    }                    ++pos;                }                m_Cols.push_back(str);            }            return;        }        catch (...) {            // exception thrown on trying to access the data            // the file isn't valid            x_CleanUp();        }    }    //    // oops, not so - must create anew...    //    try {        _TRACE("CSQLiteTable: input = " << input_file               << " db = " << temp_file);        string line;        vector<string> toks;        m_Sqlite.Reset(new CSQLite(temp_file, delete_file));        //        // first, parse the header line        // this contains the column descriptions        //        CNcbiIfstream istr(input_file.c_str());        int cols = 0;        while (NcbiGetlineEOL(istr, line)) {            if (line.empty()  ||  line[0] == '#') {                continue;            }            NStr::Tokenize(line, "\t", m_Cols);            if (m_Cols.size() == 0) {                continue;            }            //            // first readable line is column headers            // we create two tables - the column header meta-table and            // the main data table            //            // create our schema            //            m_Sqlite->Execute("create table TableCols ("                              "col VARCHAR(32) NOT NULL, "                              "name VARCHAR(255) NOT NULL, "                              "desc VARCHAR(255) NULL)");            int col_idx = 0;            string schema;            ITERATE(vector<string>, iter, m_Cols) {                string str(*iter);                NStr::ToLower(str);                string::size_type pos = 0;                while ( (pos = str.find_first_of("'", pos)) != string::npos) {                    str.insert(pos, "\\");                    pos += 2;                }                m_Sqlite->Execute("insert into TableCols (col, name) "                                  "values ('col" +                                  NStr::IntToString(col_idx) + "', '" +                                  str + "')");                if ( !schema.empty() ) {                    schema += ", ";                }                schema += "col" + NStr::IntToString(col_idx);                ++col_idx;            }            schema = "create table TableData (\n"                     "row_idx INTEGER PRIMARY KEY,\n" + schema + ");";            m_Sqlite->Execute(schema);            cols = m_Cols.size();            break;        }        //        // now, process the actual data        //        m_Sqlite->Execute("begin");        int row_idx = 0;        while (NcbiGetlineEOL(istr, line)) {            if (line.empty()  ||  line[0] == '#') {                continue;            }            toks.clear();            NStr::Tokenize(line, "\t", toks);            if (toks.size() == 0) {                continue;            }            //            // parse a row            //            string schema(NStr::IntToString(row_idx++));            ITERATE(vector<string>, iter, toks) {                string str(*iter);                string::size_type pos = 0;                while ( (pos = str.find_first_of("'")) != string::npos) {                    // escape single quotes                    str.insert(pos, "\\");                    pos += 2;                }                if ( !schema.empty() ) {                    schema += ",\n";                }                schema += "'" + *iter + "'";            }            for (int i = toks.size(); i < cols;  ++i) {                if ( !schema.empty() ) {                    schema += ",\n";                }                schema += "''";            }            schema = "insert into TableData values (\n" + schema + ");";            m_Sqlite->Execute(schema);        }        m_Sqlite->Execute("end");        CRef<CSQLiteQuery> q            (m_Sqlite->Compile("select count(*) from TableData;"));        int count = 0;        const char** data = NULL;        const char** col_names = NULL;        if (q->NextRow(count, data, col_names)) {            m_NumRows = NStr::StringToInt(data[0]);            LOG_POST(Info << "CSQLiteTable: inserted "                     << data[0] << " items into local db");        } else {            LOG_POST(Info << "compiled query failed");        }    }    catch (...) {        x_CleanUp();        throw;    }}CSQLiteTable::~CSQLiteTable(){    x_CleanUp();}void CSQLiteTable::x_CleanUp(){    m_Sqlite.Reset();    // now, we can (potentially) delete our file    if (m_DeleteFile) {        CFile file(m_TmpFileName);        file.Remove();    }}CSQLite& CSQLiteTable::SetDB(void){    return *m_Sqlite;}int CSQLiteTable::GetNumRows(void) const{    return m_NumRows;}int CSQLiteTable::GetNumCols(void) const{    return m_Cols.size();}void CSQLiteTable::GetRow(int row, list<string>& data) const{    _ASSERT(row >= 0  &&  row < m_NumRows);    CRef<CSQLiteQuery> q        (m_Sqlite->Compile("select * from TableData where row_idx = "                           + NStr::IntToString(row)));    data.clear();    if ( !q ) {        return;    }    int count = 0;    const char** row_data = NULL;    const char** cols = NULL;    q->NextRow(count, row_data, cols);    if ( !row_data ) {        return;    }    for (int i = 1;  i < count;  ++i) {        data.push_back(row_data[i]);    }}void CSQLiteTable::GetColumnTitle(int col, string& title) const{    _ASSERT(col >= 0  && col < m_Cols.size());    CRef<CSQLiteQuery> q        (m_Sqlite->Compile("select name from TableCols where col = 'col"                           + NStr::IntToString(col) + "'"));    title.erase();    if ( !q ) {        return;    }    int count = 0;    const char** row_data = NULL;    const char** cols = NULL;    q->NextRow(count, row_data, cols);    if ( !row_data ) {        return;    }    title = row_data[0];}void CSQLiteTable::GetColumnTitles(list<string>& titles) const{    CRef<CSQLiteQuery> q        (m_Sqlite->Compile("select name from TableCols "                           "where col like 'col%'"));    titles.clear();    if ( !q ) {        return;    }    int count = 0;    const char** row_data = NULL;    const char** cols = NULL;    while (q->NextRow(count, row_data, cols)) {        titles.push_back(row_data[0]);    }}// access an iterator for the entire tableCSQLiteTable::TIterator CSQLiteTable::Begin(void){    return Begin("select * from TableData");}// obtain an iterator valid for a given IDCSQLiteTable::TIterator CSQLiteTable::Begin(const CSeq_id& id){    return Begin();}// obtain an iterator valid for a given locationCSQLiteTable::TIterator CSQLiteTable::Begin(const CSeq_loc& id){    return Begin();}// obtain an iterator valid for a given SQL queryCSQLiteTable::TIterator CSQLiteTable::Begin(const string& query){    CRef<CSQLiteQuery> q(m_Sqlite->Compile(query));    if ( !q ) {        return TIterator();    }    return TIterator(new CSQLiteTableIterator(*q));}END_NCBI_SCOPE/* * =========================================================================== * $Log: sqlite_table.cpp,v $ * Revision 1000.1  2004/06/01 19:42:49  gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3 * * Revision 1.3  2004/05/21 21:42:53  gorelenk * Added PCH ncbi_pch.hpp * * Revision 1.2  2003/10/02 18:21:20  dicuccio * Added Unix projects.  Compilation fixes for gcc on Linux * * Revision 1.1  2003/10/02 17:50:48  dicuccio * Initial revision * * =========================================================================== */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?