2019-09-30 00:34:56 +00:00
# include "ocdb.h"
# include "debug.h"
# include "okapi.h"
# include <string>
# include <fstream>
# include <map>
# include <sqlite3.h>
# include <nlohmann/json.hpp>
using json = nlohmann : : json ;
// using namespace std::literals::string_literals;
2020-02-11 16:34:23 +00:00
OCdb : : OCdb ( const std : : string & db_file ) {
2020-01-25 15:33:57 +00:00
int res = 0 ;
2019-09-30 00:34:56 +00:00
res = sqlite3_open ( db_file . c_str ( ) , & db ) ;
if ( res ! = SQLITE_OK ) {
Debug ( 1 ) < < sqlite3_errmsg ( db ) ;
throw 1 ;
}
2019-11-04 20:40:24 +00:00
if ( ! read_revision ( ) ) {
Debug ( 1 ) < < " Error reading database revision, database may be corrupt or empty. \n " ;
}
2019-09-30 00:34:56 +00:00
}
OCdb : : ~ OCdb ( ) {
sqlite3_close ( db ) ;
}
2020-02-11 16:34:23 +00:00
bool OCdb : : request ( const std : : string & req ) const {
2019-09-30 00:34:56 +00:00
int res ;
res = sqlite3_prepare_v2 ( db , req . c_str ( ) , req . length ( ) + 1 , & stmt , NULL ) ;
if ( res ! = SQLITE_OK ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < req < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-09-30 00:34:56 +00:00
return 0 ;
}
res = sqlite3_step ( stmt ) ;
if ( res ! = SQLITE_DONE ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < req < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-09-30 00:34:56 +00:00
return 0 ;
}
sqlite3_finalize ( stmt ) ;
return 1 ;
}
2020-02-11 16:34:23 +00:00
bool OCdb : : init ( const std : : string & dump_path ) {
2020-03-02 18:23:34 +00:00
request ( " BEGIN TRANSACTION; " ) ;
if ( ! request ( " DROP TABLE IF EXISTS caches; " ) | |
! request ( " DROP TABLE IF EXISTS logs; " ) | |
! request ( " DROP TABLE IF EXISTS revision; " ) )
throw 1 ;
if ( ! request ( " CREATE TABLE IF NOT EXISTS revision (revision INTEGER PRIMARY KEY); " ) | |
2020-03-02 18:34:30 +00:00
! request ( " CREATE TABLE IF NOT EXISTS caches (code TEXT PRIMARY KEY, name TEXT, location TEXT, type TEXT, status TEXT, size TEXT, difficulty INTEGER, terrain INTEGER, country TEXT, region TEXT, owner TEXT); " ) | |
2020-03-02 20:55:19 +00:00
! request ( " CREATE TABLE IF NOT EXISTS logs (uuid TEXT PRIMARY KEY, cache_code TEXT, date TEXT, user TEXT, type INTEGER); " ) | |
2020-03-02 18:23:34 +00:00
! request ( " CREATE INDEX idx_user on logs (user, type); " ) )
throw 1 ;
request ( " COMMIT; " ) ;
2019-11-04 20:44:08 +00:00
2019-09-30 00:34:56 +00:00
std : : ifstream file ( dump_path + " index.json " ) ;
json j ;
file > > j ;
revision = j [ " revision " ] ;
2019-10-06 00:44:58 +00:00
request ( " BEGIN TRANSACTION; " ) ;
2019-09-30 00:34:56 +00:00
request ( " INSERT INTO revision VALUES ( " + std : : to_string ( revision ) + " ); " ) ;
for ( auto & el : j [ " data_files " ] . items ( ) ) {
init_part ( dump_path + el . value ( ) . get < std : : string > ( ) ) ;
}
2019-10-06 00:46:07 +00:00
request ( " COMMIT; " ) ;
2019-09-30 00:34:56 +00:00
return 1 ;
}
2020-02-11 16:34:23 +00:00
bool OCdb : : init_part ( const std : : string & json_file ) {
2019-10-01 15:11:38 +00:00
Debug ( 2 ) < < " Processing file: " < < json_file < < ' \n ' ;
2019-11-04 20:44:08 +00:00
2019-09-30 00:34:56 +00:00
std : : ifstream file ( json_file ) ;
json j ;
file > > j ;
2019-10-01 15:11:38 +00:00
Debug ( 5 ) < < " File: " < < json_file < < " read. \n " ;
2019-09-30 00:34:56 +00:00
for ( auto & el : j . items ( ) ) {
parse_item ( el . value ( ) ) ;
}
return 1 ;
}
2020-02-11 16:34:23 +00:00
bool OCdb : : update ( const Okapi & oc ) {
2020-01-25 15:33:57 +00:00
if ( revision = = 0 ) {
Debug ( 1 ) < < " Cannot update database, you need to init it first with a full dump. \n " ;
throw 1 ;
}
2019-09-30 23:49:25 +00:00
Debug ( 2 ) < < " Fetching changelog since revision " < < revision < < " . \n " ;
std : : string output = oc . get_changelog_json ( revision ) ;
json j = json : : parse ( output ) ;
2019-10-06 00:44:58 +00:00
request ( " BEGIN TRANSACTION; " ) ;
2019-09-30 23:49:25 +00:00
for ( auto & el : j [ " changelog " ] . items ( ) ) {
parse_item ( el . value ( ) ) ;
}
2019-10-06 00:46:07 +00:00
set_revision ( j [ " revision " ] ) ;
request ( " COMMIT; " ) ;
2019-09-30 23:49:25 +00:00
if ( j [ " more " ] )
update ( oc ) ;
2019-09-30 00:34:56 +00:00
return 1 ;
}
2020-02-11 16:34:23 +00:00
bool OCdb : : parse_item ( const json & j ) {
2020-03-02 21:58:34 +00:00
if ( j . count ( " object_type " ) & & j [ " object_type " ] = = " geocache " ) {
if ( j . count ( " change_type " ) & & j [ " change_type " ] = = " replace " ) {
2019-10-01 15:11:38 +00:00
Debug ( 5 ) < < " Inserting/updating cache " < < j [ " object_key " ] [ " code " ] . get < std : : string > ( ) < < " . \n " ;
2019-11-04 20:44:08 +00:00
// if (j["object_key"]["code"] != j["data"]["code"]) {
// Debug(1) << "Code change " << j["object_key"]["code"] << " -> " << j["data"]["code"] <<'\n';
// }
2019-09-30 00:34:56 +00:00
update_cache ( j ) ;
2020-03-02 21:58:34 +00:00
} else if ( j . count ( " change_type " ) & & j [ " change_type " ] = = " delete " ) {
2019-10-01 15:11:38 +00:00
Debug ( 2 ) < < " Deleting cache " < < j [ " object_key " ] [ " code " ] . get < std : : string > ( ) < < " . \n " ;
2019-09-30 00:34:56 +00:00
std : : string sql = " DELETE FROM caches WHERE code=' " + j [ " object_key " ] [ " code " ] . get < std : : string > ( ) + " '; " ;
request ( sql ) ;
2019-11-04 20:44:08 +00:00
} else {
2019-09-30 00:34:56 +00:00
Debug ( 1 ) < < " Incorrect change type: " < < j [ " change_type " ] < < " . \n " ;
}
2020-03-02 21:58:34 +00:00
} else if ( j . count ( " object_type " ) & & j [ " object_type " ] = = " log " ) {
2019-09-30 00:34:56 +00:00
if ( j [ " change_type " ] = = " replace " ) {
2019-10-01 15:11:38 +00:00
Debug ( 3 ) < < " Updating log " < < j [ " object_key " ] [ " uuid " ] < < " . \n " ;
2019-09-30 00:34:56 +00:00
update_log ( j ) ;
2020-03-02 21:58:34 +00:00
} else if ( j . count ( " change_type " ) & & j [ " change_type " ] = = " delete " ) {
2019-09-30 00:34:56 +00:00
Debug ( 2 ) < < " Deleting log " < < j [ " object_key " ] [ " uuid " ] < < " . \n " ;
std : : string sql = " DELETE FROM logs WHERE uuid=' " + j [ " object_key " ] [ " uuid " ] . get < std : : string > ( ) + " '; " ;
request ( sql ) ;
2019-11-04 20:44:08 +00:00
} else {
2019-09-30 00:34:56 +00:00
Debug ( 1 ) < < " Incorrect change type: " < < j [ " change_type " ] < < " . \n " ;
}
2019-11-04 20:44:08 +00:00
} else {
2019-09-30 00:34:56 +00:00
Debug ( 1 ) < < " Incorrect object type: " < < j [ " object_type " ] < < " . \n " ;
}
return 1 ;
}
2020-02-11 16:34:23 +00:00
bool OCdb : : update_cache ( const json & j ) {
2019-11-04 20:44:08 +00:00
// (code TEXT PRIMARY KEY, name TEXT, location TEXT, type TEXT, status TEXT, size TEXT, difficulty REAL, terrain REAL, country TEXT, region TEXT, owner TEXT)
2019-09-30 00:34:56 +00:00
std : : map < std : : string , std : : string > fields ;
2020-03-02 18:34:30 +00:00
std : : map < std : : string , short > fields2 ;
2019-09-30 00:34:56 +00:00
int res ;
2020-03-02 21:58:14 +00:00
if ( ! j . count ( " object_key " ) | | ! j [ " object_key " ] . count ( " code " ) | | ! j . count ( " data " ) ) return 0 ;
2019-09-30 00:34:56 +00:00
std : : string code = j [ " object_key " ] [ " code " ] . get < std : : string > ( ) ;
2020-03-02 21:58:14 +00:00
if ( j [ " data " ] . count ( " names " ) & & j [ " data " ] [ " names " ] . count ( " pl " ) & & ! j [ " data " ] [ " names " ] [ " pl " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " name " ] = j [ " data " ] [ " names " ] [ " pl " ] . get < std : : string > ( ) ;
2020-03-02 21:58:14 +00:00
else if ( j [ " data " ] . count ( " names " ) & & j [ " data " ] [ " names " ] . count ( " en " ) & & ! j [ " data " ] [ " names " ] [ " en " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " name " ] = j [ " data " ] [ " names " ] [ " en " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " location " ) & & ! j [ " data " ] [ " location " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " location " ] = j [ " data " ] [ " location " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " type " ) & & ! j [ " data " ] [ " type " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " type " ] = j [ " data " ] [ " type " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " status " ) & & ! j [ " data " ] [ " status " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " status " ] = j [ " data " ] [ " status " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " size2 " ) & & ! j [ " data " ] [ " size2 " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " size " ] = j [ " data " ] [ " size2 " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " difficulty " ) & & ! j [ " data " ] [ " difficulty " ] . is_null ( ) )
2020-03-02 18:34:30 +00:00
fields2 [ " difficulty " ] = 2 * j [ " data " ] [ " difficulty " ] . get < float > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " terrain " ) & & ! j [ " data " ] [ " terrain " ] . is_null ( ) )
2020-03-02 18:34:30 +00:00
fields2 [ " terrain " ] = 2 * j [ " data " ] [ " terrain " ] . get < float > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " country " ) & & ! j [ " data " ] [ " country " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " country " ] = j [ " data " ] [ " country " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " region " ) & & ! j [ " data " ] [ " region " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " region " ] = j [ " data " ] [ " region " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
else if ( j [ " data " ] . count ( " state " ) & & ! j [ " data " ] [ " state " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " region " ] = j [ " data " ] [ " state " ] . get < std : : string > ( ) ;
2020-03-02 21:58:14 +00:00
if ( j [ " data " ] . count ( " owner " ) & & j [ " data " ] [ " owner " ] . count ( " uuid " ) & & ! j [ " data " ] [ " owner " ] [ " uuid " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " owner " ] = j [ " data " ] [ " owner " ] [ " uuid " ] . get < std : : string > ( ) ;
2019-10-01 15:29:17 +00:00
if ( fields . empty ( ) & & fields2 . empty ( ) )
2020-02-11 16:34:52 +00:00
return 1 ;
2019-10-01 15:29:17 +00:00
2019-09-30 00:34:56 +00:00
std : : string sql = " INSERT INTO caches (code, " ;
for ( auto & i : fields )
sql + = i . first + ' , ' ;
for ( auto & i : fields2 )
sql + = i . first + ' , ' ;
sql . pop_back ( ) ;
sql + = " ) VALUES (' " + code + " ', " ;
2019-10-06 00:58:24 +00:00
for ( __attribute__ ( ( unused ) ) auto & i : fields )
2019-09-30 00:34:56 +00:00
sql + = " ?, " ;
2019-10-06 00:58:24 +00:00
for ( __attribute__ ( ( unused ) ) auto & i : fields2 )
2019-09-30 00:34:56 +00:00
sql + = " ?, " ;
sql . pop_back ( ) ;
sql + = " ) ON CONFLICT(code) DO UPDATE SET " ;
for ( auto & i : fields )
sql + = i . first + " =excluded. " + i . first + ' , ' ;
for ( auto & i : fields2 )
sql + = i . first + " =excluded. " + i . first + ' , ' ;
sql . pop_back ( ) ;
sql + = ' ; ' ;
res = sqlite3_prepare_v2 ( db , sql . c_str ( ) , sql . length ( ) + 1 , & stmt , NULL ) ;
if ( res ! = SQLITE_OK ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-09-30 00:34:56 +00:00
return 0 ;
}
int n = 1 ;
for ( auto & i : fields ) {
sqlite3_bind_text ( stmt , n + + , i . second . c_str ( ) , - 1 , nullptr ) ;
}
for ( auto & i : fields2 ) {
2020-03-02 18:34:30 +00:00
sqlite3_bind_int ( stmt , n + + , i . second ) ;
2019-09-30 00:34:56 +00:00
}
res = sqlite3_step ( stmt ) ;
if ( res ! = SQLITE_DONE ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-09-30 00:34:56 +00:00
return 0 ;
}
sqlite3_finalize ( stmt ) ;
return 1 ;
}
2020-02-11 16:34:23 +00:00
bool OCdb : : update_log ( const json & j ) {
2019-11-04 20:44:08 +00:00
// logs (uuid TEXT PRIMARY KEY, cache_code TEXT, date TEXT, user TEXT, type TEXT);"))
2019-09-30 00:34:56 +00:00
std : : map < std : : string , std : : string > fields ;
2020-03-02 20:55:19 +00:00
std : : map < std : : string , short > fields2 ;
2019-09-30 00:34:56 +00:00
int res ;
2020-03-02 21:58:14 +00:00
if ( ! j . count ( " object_key " ) | | ! j [ " object_key " ] . count ( " uuid " ) | | ! j . count ( " data " ) ) return 0 ;
2019-09-30 00:34:56 +00:00
std : : string uuid = j [ " object_key " ] [ " uuid " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " cache_code " ) & & ! j [ " data " ] [ " cache_code " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " cache_code " ] = j [ " data " ] [ " cache_code " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " date " ) & & ! j [ " data " ] [ " date " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " date " ] = j [ " data " ] [ " date " ] . get < std : : string > ( ) ;
2020-03-02 21:58:14 +00:00
if ( j [ " data " ] . count ( " user " ) & & j [ " data " ] [ " user " ] . count ( " uuid " ) & & ! j [ " data " ] [ " user " ] [ " uuid " ] . is_null ( ) )
2019-09-30 00:34:56 +00:00
fields [ " user " ] = j [ " data " ] [ " user " ] [ " uuid " ] . get < std : : string > ( ) ;
2020-03-02 21:58:34 +00:00
if ( j [ " data " ] . count ( " type " ) & & ! j [ " data " ] [ " type " ] . is_null ( ) ) {
2020-03-02 20:55:19 +00:00
if ( j [ " data " ] [ " type " ] . get < std : : string > ( ) = = " Didn't find it " )
fields2 [ " type " ] = 0 ;
else if ( j [ " data " ] [ " type " ] . get < std : : string > ( ) = = " Found it " )
fields2 [ " type " ] = 1 ;
else
fields2 [ " type " ] = - 1 ;
}
2019-10-01 15:29:17 +00:00
if ( fields . empty ( ) )
2020-02-11 16:34:52 +00:00
return 1 ;
2019-10-01 15:29:17 +00:00
2019-09-30 00:34:56 +00:00
std : : string sql = " INSERT INTO logs (uuid, " ;
for ( auto & i : fields )
sql + = i . first + ' , ' ;
2020-03-02 20:55:19 +00:00
for ( auto & i : fields2 )
sql + = i . first + ' , ' ;
2019-09-30 00:34:56 +00:00
sql . pop_back ( ) ;
sql + = " ) VALUES (' " + uuid + " ', " ;
2019-10-06 00:58:24 +00:00
for ( __attribute__ ( ( unused ) ) auto & i : fields )
2019-09-30 00:34:56 +00:00
sql + = " ?, " ;
2020-03-02 20:55:19 +00:00
for ( __attribute__ ( ( unused ) ) auto & i : fields2 )
sql + = " ?, " ;
2019-09-30 00:34:56 +00:00
sql . pop_back ( ) ;
sql + = " ) ON CONFLICT(uuid) DO UPDATE SET " ;
for ( auto & i : fields )
sql + = i . first + " =excluded. " + i . first + ' , ' ;
sql . pop_back ( ) ;
sql + = ' ; ' ;
res = sqlite3_prepare_v2 ( db , sql . c_str ( ) , sql . length ( ) + 1 , & stmt , NULL ) ;
if ( res ! = SQLITE_OK ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-09-30 00:34:56 +00:00
return 0 ;
}
int n = 1 ;
for ( auto & i : fields ) {
sqlite3_bind_text ( stmt , n + + , i . second . c_str ( ) , - 1 , nullptr ) ;
}
2020-03-02 20:55:19 +00:00
for ( auto & i : fields2 ) {
sqlite3_bind_int ( stmt , n + + , i . second ) ;
}
2019-09-30 00:34:56 +00:00
res = sqlite3_step ( stmt ) ;
if ( res ! = SQLITE_DONE ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-09-30 00:34:56 +00:00
return 0 ;
}
sqlite3_finalize ( stmt ) ;
return 1 ;
}
2019-09-30 23:48:49 +00:00
bool OCdb : : read_revision ( ) {
int res ;
std : : string sql = " SELECT revision FROM revision; " ;
res = sqlite3_prepare_v2 ( db , sql . c_str ( ) , sql . length ( ) + 1 , & stmt , NULL ) ;
if ( res ! = SQLITE_OK ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-09-30 23:48:49 +00:00
return 0 ;
}
res = sqlite3_step ( stmt ) ;
if ( res ! = SQLITE_ROW ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-09-30 23:48:49 +00:00
return 0 ;
}
revision = sqlite3_column_int ( stmt , 0 ) ;
sqlite3_finalize ( stmt ) ;
Debug ( 2 ) < < " Revision: " < < revision < < ' \n ' ;
return 1 ;
}
2019-10-03 22:43:39 +00:00
2020-02-11 16:34:23 +00:00
Caches OCdb : : get_user_caches_not_found ( const std : : string & uuid ) const {
2019-10-04 00:30:17 +00:00
int res ;
Caches cc ;
2020-05-24 14:56:10 +00:00
std : : string sql = " SELECT code, location, name, region FROM caches WHERE status = 'Available' AND NOT EXISTS (SELECT cache_code FROM logs WHERE cache_code = code AND type = 1 and user = ?1) AND owner != ?1; " ;
2019-10-04 00:30:17 +00:00
res = sqlite3_prepare_v2 ( db , sql . c_str ( ) , sql . length ( ) + 1 , & stmt , NULL ) ;
if ( res ! = SQLITE_OK ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-10-04 00:30:17 +00:00
throw 0 ;
}
sqlite3_bind_text ( stmt , 1 , uuid . c_str ( ) , - 1 , nullptr ) ;
res = sqlite3_step ( stmt ) ;
while ( res = = SQLITE_ROW ) {
2020-06-02 22:21:31 +00:00
Cache c ;
2020-05-24 14:56:10 +00:00
if ( sqlite3_column_text ( stmt , 0 ) ) c . code = reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 0 ) ) ;
2020-07-06 15:13:30 +00:00
if ( sqlite3_column_text ( stmt , 1 ) ) c . pos = Position ( reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 1 ) ) ) ;
2020-05-24 14:56:10 +00:00
if ( sqlite3_column_text ( stmt , 2 ) ) c . name = reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 2 ) ) ;
if ( sqlite3_column_text ( stmt , 3 ) ) c . region = reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 3 ) ) ;
2020-03-20 00:49:06 +00:00
c . status = ok ;
2020-02-29 01:04:55 +00:00
cc . push_back ( c ) ;
2019-10-04 00:30:17 +00:00
res = sqlite3_step ( stmt ) ;
}
2019-11-04 20:44:08 +00:00
if ( res ! = SQLITE_DONE ) {
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-10-04 00:30:17 +00:00
throw 0 ;
}
sqlite3_finalize ( stmt ) ;
return cc ;
}
2020-02-11 16:34:23 +00:00
Caches OCdb : : get_user_caches ( const std : : string & uuid , __attribute__ ( ( unused ) ) int count ) const {
2019-10-04 00:30:17 +00:00
int res ;
2019-10-03 22:43:39 +00:00
Caches cc ;
2020-06-02 22:21:31 +00:00
2019-11-04 20:44:08 +00:00
//code TEXT PRIMARY KEY, name TEXT, location TEXT, type TEXT, status TEXT, size TEXT, difficulty REAL, terrain REAL, country TEXT, region TEXT, owner TEXT)
2020-03-20 00:49:06 +00:00
std : : string sql = " SELECT code, location, type, size, difficulty, terrain, country, region, owner, status FROM caches WHERE EXISTS (SELECT cache_code FROM logs WHERE cache_code = code AND type = 1 and user = ?); " ;
2019-10-04 00:30:17 +00:00
res = sqlite3_prepare_v2 ( db , sql . c_str ( ) , sql . length ( ) + 1 , & stmt , NULL ) ;
if ( res ! = SQLITE_OK ) {
2019-11-04 20:44:08 +00:00
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-10-04 00:30:17 +00:00
throw 0 ;
}
sqlite3_bind_text ( stmt , 1 , uuid . c_str ( ) , - 1 , nullptr ) ;
res = sqlite3_step ( stmt ) ;
while ( res = = SQLITE_ROW ) {
2020-06-02 22:21:31 +00:00
Cache c ;
2020-05-24 14:56:10 +00:00
if ( sqlite3_column_text ( stmt , 0 ) ) c . code = reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 0 ) ) ;
2020-07-06 15:13:30 +00:00
if ( sqlite3_column_text ( stmt , 1 ) ) c . pos = Position ( reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 1 ) ) ) ;
2020-05-24 14:56:10 +00:00
if ( sqlite3_column_text ( stmt , 2 ) ) c . type = reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 2 ) ) ;
if ( sqlite3_column_text ( stmt , 3 ) ) c . size = reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 3 ) ) ;
2020-03-02 18:34:30 +00:00
c . diff = sqlite3_column_int ( stmt , 4 ) / 2.0 ;
c . terr = sqlite3_column_int ( stmt , 5 ) / 2.0 ;
2019-11-04 20:44:08 +00:00
//c.country = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 6));
2020-05-24 14:56:10 +00:00
if ( sqlite3_column_text ( stmt , 7 ) ) c . region = reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 7 ) ) ;
if ( sqlite3_column_text ( stmt , 8 ) ) c . owner_uuid = reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 8 ) ) ; // TODO: we don't know owner's nick
2020-03-20 00:49:06 +00:00
2020-05-24 14:56:10 +00:00
if ( sqlite3_column_text ( stmt , 9 ) ) {
std : : string tmp = reinterpret_cast < const char * > ( sqlite3_column_text ( stmt , 9 ) ) ;
if ( tmp = = " Available " )
2020-03-20 00:49:06 +00:00
c . status = ok ;
else if ( tmp = = " Temporarily unavailable " )
c . status = disabled ;
else if ( tmp = = " Archived " )
c . status = archived ;
else
c . status = unknown ;
2020-07-06 11:57:51 +00:00
} else
c . status = unknown ;
2020-03-20 00:49:06 +00:00
2020-02-29 01:04:55 +00:00
cc . push_back ( c ) ;
2019-10-04 00:30:17 +00:00
res = sqlite3_step ( stmt ) ;
}
2019-11-04 20:44:08 +00:00
if ( res ! = SQLITE_DONE ) {
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
2019-10-04 00:30:17 +00:00
throw 0 ;
}
2020-06-02 22:24:02 +00:00
sqlite3_finalize ( stmt ) ;
2019-10-03 22:43:39 +00:00
return cc ;
}
2019-10-06 00:46:07 +00:00
2020-02-11 16:34:23 +00:00
int OCdb : : get_revision ( ) const {
2019-10-06 00:46:07 +00:00
return revision ;
}
void OCdb : : set_revision ( int rev ) {
revision = rev ;
request ( " UPDATE revision SET revision = " + std : : to_string ( revision ) + ' ; ' ) ;
}
2020-06-02 22:24:54 +00:00
std : : map < std : : string , int > OCdb : : get_region_stats ( ) {
std : : map < std : : string , int > count ;
int res ;
std : : vector < std : : string > regions = {
" dolnośląskie " ,
" śląskie " ,
" kujawsko-pomorskie " ,
" łódzkie " ,
" lubelskie " ,
" lubuskie " ,
" małopolskie " ,
" mazowieckie " ,
" opolskie " ,
" podkarpackie " ,
" podlaskie " ,
" pomorskie " ,
" świętokrzyskie " ,
" warmińsko-mazurskie " ,
" wielkopolskie " ,
" zachodniopomorskie "
} ;
//code TEXT PRIMARY KEY, name TEXT, location TEXT, type TEXT, status TEXT, size TEXT, difficulty REAL, terrain REAL, country TEXT, region TEXT, owner TEXT)
std : : string sql = " SELECT COUNT(code) FROM caches WHERE status = 'Available' AND region = ?; " ;
res = sqlite3_prepare_v2 ( db , sql . c_str ( ) , sql . length ( ) + 1 , & stmt , NULL ) ;
if ( res ! = SQLITE_OK ) {
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
throw 0 ;
}
for ( auto reg : regions ) {
sqlite3_bind_text ( stmt , 1 , reg . c_str ( ) , - 1 , nullptr ) ;
res = sqlite3_step ( stmt ) ;
if ( res ! = SQLITE_ROW ) {
Debug ( 1 ) < < " Request \" " < < sql < < " \" failed: \n "
< < sqlite3_errmsg ( db ) ;
throw 0 ;
}
count [ reg ] = sqlite3_column_int ( stmt , 0 ) ;
sqlite3_reset ( stmt ) ;
sqlite3_clear_bindings ( stmt ) ;
}
sqlite3_finalize ( stmt ) ;
return count ;
}