OPT added to MAkefile; KanjiView::Cell constructor: fg,bg changed to int (Fl_Color...
[aoi.git] / src / sqlite3.hxx
blob0a8eb211c70f419d3fcc22dac68f7864ef76b01a
1 /*
2 Copyright 2013 Karel Matas
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 /*! \file sqlite3.hxx
23 #ifndef _SQLITE3_HXX
24 #define _SQLITE3_HXX
26 #include "3rdparty/sqlite3.h"
27 #include <exception>
28 #include <vector>
29 #include <string>
30 #include <sstream>
31 #include <cstring>
32 #include <stdexcept>
34 using std::vector;
35 using std::string;
37 namespace SQLite3 {
39 //////////////////////////////////////////////////////////////////////////
40 // EXCEPTIONS
42 class CantOpenDatabase : public std::exception {
43 private:
44 string msg_;
45 public:
46 CantOpenDatabase(const string &filename): msg_(filename) {};
47 const char *what() const noexcept {return msg_.c_str();};
51 class DatabaseError : public std::exception {
52 private:
53 string msg_;
54 string query_;
55 public:
56 DatabaseError(const string &msg, const string &query)
57 : msg_(msg.c_str()), query_(query){};
58 const char *what() const noexcept {return msg_.c_str();};
59 //! Returns details about executed query.
60 const char *query() const {return query_.c_str();};
64 //////////////////////////////////////////////////////////////////////////
65 // FUNCTIONS
67 /*!
68 * Replaces ' with '' and " with \".
70 inline string escape ( const char *s )
72 if ( !strlen(s) )
73 return "";
75 std::stringstream ss;
76 for ( size_t i=0; i<strlen(s); i++ ){
77 ss << s[i];
78 if ( s[i] == '\'' )
79 ss << "'";
80 else if ( s[i] == '"' )
81 ss << "\"";
83 return ss.str();
86 inline string escape ( const string &s ){ return escape(s.c_str()); }
89 //////////////////////////////////////////////////////////////////////////
90 // class SQLite3
92 class SQLite3
94 private:
95 sqlite3 *db_ = nullptr;
96 vector<string> data_ = {};
97 vector<string> columns_ = {};
99 public:
101 * Constructor. Calls open().
102 * \param filename Name of the sqlite3 database file.
104 SQLite3 ( const char *filename ) { open( filename ); }
106 //! Destructor. Calls close().
107 ~SQLite3 () { close(); }
110 * Opens sqlite3 database.
111 * \exception CantOpenDatabase
112 * \param filename NAme of the sqlite3 database.
114 void open( const char *filename ){
115 if( sqlite3_open(filename, &db_) != SQLITE_OK ) {
116 close();
117 throw CantOpenDatabase(filename);
121 //! Closes database.
122 void close() { sqlite3_close(db_); }
124 //! sqlite3_exec calls this function for each row
125 static int callback(void *parent, int argc, char **argv, char **column) {
126 // put column names into vector<string> columns_
127 if ( ((SQLite3*)parent)->data_.empty() ) {
128 for( int i=0; i<argc; i++ )
129 ((SQLite3*)parent)->columns_.push_back( column[i] );
131 // put row data into vector<string> data_
132 for( int i=0; i<argc; i++ )
133 ((SQLite3*)parent)->data_.push_back( argv[i] ? argv[i] : "" );
134 return 0;
137 //! Returns all data (same data as query() ).
138 inline vector<string> data () const { return data_; };
140 //! Returns column names
141 inline vector<string> columns () const { return columns_; };
143 //! Returns # of returned rows ( data().size()/columns().size() )
144 inline size_t result_rows () const
145 { return data_.empty() ? 0:data_.size()/columns_.size(); };
148 * Executes SQLite query.
149 * Query can contain more commands separated with semicolon.
150 * \exception CantOpenDatabase
151 * \exception DatabaseError
152 * \param query SQLite query
153 * \return Vector of strings with query results. Order of elements is: row1_col1, row1_col2, .. row1_colN, row2_col1, .. row2_colN, .. , rowM_col1, .., rowM_colN
154 * \sa script()
156 vector<string> query( const char *query ){
157 if ( !db_ )
158 throw CantOpenDatabase("SQLite3::query(): db_ is NULL");
159 char *err = nullptr;
160 if ( !data_.empty() ) data_.clear();
161 if ( !columns_.empty() ) columns_.clear();
162 int rc = sqlite3_exec( db_, query, SQLite3::callback, (void*)this, &err);
163 string s(err?err:"");
164 sqlite3_free(err);
165 if ( rc != SQLITE_OK )
166 throw DatabaseError(s,query);
167 return data_;
171 * Loads and executes file containing SQLite script.
172 * \exception std::runtime_error
173 * \param path path to script file
174 * \sa query()
176 void script ( const char *path ){
177 std::ifstream f(path);
178 if ( f.is_open() ){
179 f.seekg( 0, f.end );
180 size_t size = f.tellg();
181 f.seekg( 0, f.beg );
182 if ( size > 0 ){
183 char buff[ size+1 ];
184 f.read( buff, size );
185 f.close();
186 query( buff );
188 else
189 throw std::runtime_error("File has zero length: " + string(path));
191 else
192 throw std::runtime_error("Can't open file: " + string(path));
196 } // namespace sqlite3
197 #endif //_SQLITE3_HXX