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 // overloaded inline function must be placed after base inline function
87 inline string
escape ( const string
&s
){ return escape(s
.c_str()); }
90 //////////////////////////////////////////////////////////////////////////
96 sqlite3
*db_
= nullptr;
97 vector
<string
> data_
= {};
98 vector
<string
> columns_
= {};
102 * Constructor. Calls open().
103 * \param filename Name of the sqlite3 database file.
105 SQLite3 ( const char *filename
) { open( filename
); }
107 //! Destructor. Calls close().
108 ~SQLite3 () { close(); }
111 * Opens sqlite3 database.
112 * \exception CantOpenDatabase
113 * \param filename NAme of the sqlite3 database.
115 void open( const char *filename
){
116 if( sqlite3_open(filename
, &db_
) != SQLITE_OK
) {
118 throw CantOpenDatabase(filename
);
123 void close() { sqlite3_close(db_
); }
125 //! sqlite3_exec calls this function for each row
126 static int callback(void *parent
, int argc
, char **argv
, char **column
) {
127 // put column names into vector<string> columns_
128 if ( ((SQLite3
*)parent
)->data_
.empty() ) {
129 for( int i
=0; i
<argc
; i
++ )
130 ((SQLite3
*)parent
)->columns_
.push_back( column
[i
] );
132 // put row data into vector<string> data_
133 for( int i
=0; i
<argc
; i
++ )
134 ((SQLite3
*)parent
)->data_
.push_back( argv
[i
] ? argv
[i
] : "" );
138 //! Returns all data (same data as query() ).
139 inline vector
<string
> data () const { return data_
; };
141 //! Returns column names
142 inline vector
<string
> columns () const { return columns_
; };
144 //! Returns # of returned rows ( data().size()/columns().size() )
145 inline size_t result_rows () const
146 { return data_
.empty() ? 0:data_
.size()/columns_
.size(); };
149 * Executes SQLite query.
150 * Query can contain more commands separated with semicolon.
151 * \exception CantOpenDatabase
152 * \exception DatabaseError
153 * \param query SQLite query
154 * \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
157 vector
<string
> query( const char *query
){
159 throw CantOpenDatabase("SQLite3::query(): db_ is NULL");
161 if ( !data_
.empty() ) data_
.clear();
162 if ( !columns_
.empty() ) columns_
.clear();
163 int rc
= sqlite3_exec( db_
, query
, SQLite3::callback
, (void*)this, &err
);
164 string
s(err
?err
:"");
166 if ( rc
!= SQLITE_OK
)
167 throw DatabaseError(s
,query
);
172 * Loads and executes file containing SQLite script.
173 * \exception std::runtime_error
174 * \param path path to script file
177 void script ( const char *path
){
178 std::ifstream
f(path
);
181 size_t size
= f
.tellg();
185 f
.read( buff
, size
);
190 throw std::runtime_error("File has zero length: " + string(path
));
193 throw std::runtime_error("Can't open file: " + string(path
));
197 } // namespace sqlite3
198 #endif //_SQLITE3_HXX