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/>.
26 #include "3rdparty/sqlite3.h"
39 //////////////////////////////////////////////////////////////////////////
42 class CantOpenDatabase
: public std::exception
{
46 CantOpenDatabase(const string
&filename
): msg_(filename
) {};
47 const char *what() const noexcept
{return msg_
.c_str();};
51 class DatabaseError
: public std::exception
{
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 //////////////////////////////////////////////////////////////////////////
68 * Replaces ' with '' and " with \".
70 inline string
escape ( const char *s
)
76 for ( size_t i
=0; i
<strlen(s
); i
++ ){
80 else if ( s
[i
] == '"' )
86 inline string
escape ( const string
&s
){ return escape(s
.c_str()); }
89 //////////////////////////////////////////////////////////////////////////
95 sqlite3
*db_
= nullptr;
96 vector
<string
> data_
= {};
97 vector
<string
> columns_
= {};
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
) {
117 throw CantOpenDatabase(filename
);
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
] : "" );
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
156 vector
<string
> query( const char *query
){
158 throw CantOpenDatabase("SQLite3::query(): db_ is NULL");
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
:"");
165 if ( rc
!= SQLITE_OK
)
166 throw DatabaseError(s
,query
);
171 * Loads and executes file containing SQLite script.
172 * \exception std::runtime_error
173 * \param path path to script file
176 void script ( const char *path
){
177 std::ifstream
f(path
);
180 size_t size
= f
.tellg();
184 f
.read( buff
, size
);
189 throw std::runtime_error("File has zero length: " + string(path
));
192 throw std::runtime_error("Can't open file: " + string(path
));
196 } // namespace sqlite3
197 #endif //_SQLITE3_HXX