2008-12-10 05:42:49 +01:00
/*
2010-02-28 01:08:10 +01:00
* This file is a part of Winix
2008-12-10 05:42:49 +01:00
* and is not publicly distributed
*
2010-02-28 22:33:06 +01:00
* Copyright ( c ) 2008 - 2010 , Tomasz Sowa
2008-12-10 05:42:49 +01:00
* All rights reserved .
*
*/
# include "db.h"
2009-04-21 22:50:55 +02:00
# include "log.h"
# include "misc.h"
2008-12-10 05:42:49 +01:00
2009-01-26 21:49:28 +01:00
Db : : Db ( bool close_at_end_ )
2008-12-10 05:42:49 +01:00
{
2009-01-26 21:49:28 +01:00
pg_conn = 0 ;
close_at_end = close_at_end_ ;
2008-12-10 05:42:49 +01:00
}
Db : : ~ Db ( )
{
2009-01-26 21:49:28 +01:00
if ( close_at_end )
Close ( ) ;
2008-12-10 05:42:49 +01:00
}
2009-01-26 21:49:28 +01:00
PGconn * Db : : GetPGconn ( )
{
return pg_conn ;
}
2008-12-10 05:42:49 +01:00
void Db : : Init ( const std : : string & d , const std : : string & u , const std : : string & p )
{
db_database = d ;
db_user = u ;
db_pass = p ;
Connect ( ) ;
}
void Db : : Connect ( )
{
2008-12-11 03:46:16 +01:00
Close ( ) ;
2008-12-10 05:42:49 +01:00
std : : ostringstream buf ;
buf < < " dbname= " < < db_database < < " user= " < < db_user < < " password= " < < db_pass ;
pg_conn = PQconnectdb ( buf . str ( ) . c_str ( ) ) ;
2009-01-27 19:43:44 +01:00
if ( pg_conn )
log < < log3 < < " Db: Socket: " < < PQsocket ( pg_conn ) < < logend ;
2008-12-10 05:42:49 +01:00
2009-01-27 19:43:44 +01:00
// warning! pg_conn can be not null but there cannnot be a connection established
// use PQstatus(pg_conn) to check whether the connection works fine
}
2008-12-10 05:42:49 +01:00
2009-01-27 19:43:44 +01:00
void Db : : SetDbParameters ( )
{
2008-12-10 05:42:49 +01:00
if ( PQsetClientEncoding ( pg_conn , " LATIN2 " ) = = - 1 )
log < < log1 < < " Db: Can't set the proper client encoding " < < logend ;
}
2009-01-27 19:43:44 +01:00
2008-12-10 05:42:49 +01:00
void Db : : Close ( )
{
if ( pg_conn )
{
PQfinish ( pg_conn ) ;
pg_conn = 0 ;
}
}
void Db : : AssertConnection ( )
{
2009-01-27 19:43:44 +01:00
bool was_connection = true ;
2008-12-10 05:42:49 +01:00
if ( ! pg_conn )
{
2009-01-27 19:43:44 +01:00
was_connection = false ;
2008-12-10 05:42:49 +01:00
Connect ( ) ;
}
2009-01-27 19:43:44 +01:00
else
2008-12-10 05:42:49 +01:00
if ( PQstatus ( pg_conn ) ! = CONNECTION_OK )
{
2009-01-27 19:43:44 +01:00
log < < log2 < < " Db: connection to the database is lost, trying to recover " < < logend ;
was_connection = false ;
2008-12-10 05:42:49 +01:00
PQreset ( pg_conn ) ;
2009-01-27 19:43:44 +01:00
}
if ( pg_conn & & PQstatus ( pg_conn ) = = CONNECTION_OK )
{
if ( was_connection = = false )
log < < log2 < < " Db: Connection to the database works fine " < < logend ;
2008-12-10 05:42:49 +01:00
2009-01-27 19:43:44 +01:00
SetDbParameters ( ) ;
}
else
{
log < < log1 < < " Db: Connection to db server cannot be established " < < logend ;
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_DB_FATAL_ERROR_DURING_CONNECTING ) ;
2008-12-10 05:42:49 +01:00
}
}
std : : string Db : : Escape ( const std : : string & s )
{
std : : string result ;
result . resize ( s . length ( ) * 2 + 1 ) ;
size_t len = PQescapeStringConn ( pg_conn , const_cast < char * > ( result . c_str ( ) ) , s . c_str ( ) , s . length ( ) , 0 ) ;
result . resize ( len ) ;
return result ;
}
std : : string Db : : Escape ( const char * s )
{
std : : string result ;
int len ;
for ( len = 0 ; s [ len ] ! = 0 ; + + len ) ;
result . resize ( len * 2 + 1 ) ;
size_t len_new = PQescapeStringConn ( pg_conn , const_cast < char * > ( result . c_str ( ) ) , s , len , 0 ) ;
result . resize ( len_new ) ;
return result ;
}
// ------------------
PGresult * Db : : AssertQuery ( const std : : string & q )
{
PGresult * r = PQexec ( pg_conn , q . c_str ( ) ) ;
if ( ! r )
{
2009-01-26 21:49:28 +01:00
log < < log1 < < " Db: Problem with query: \" " < < q < < ' \" ' < < logend ;
log < < log1 < < " Db: " < < PQerrorMessage ( pg_conn ) < < logend ;
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_DB_INCORRECT_QUERY ) ;
2008-12-10 05:42:49 +01:00
}
return r ;
}
void Db : : AssertResultStatus ( PGresult * r , ExecStatusType t )
{
if ( PQresultStatus ( r ) ! = t )
{
log < < " Db: Incorrect result status: " < < PQerrorMessage ( pg_conn ) < < logend ;
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_DB_INCORRENT_RESULT_STATUS ) ;
2008-12-10 05:42:49 +01:00
}
}
int Db : : AssertColumn ( PGresult * r , const char * column_name )
{
int c = PQfnumber ( r , column_name ) ;
if ( c = = - 1 )
{
log < < log1 < < " Db: there is no column: " < < column_name < < logend ;
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_DB_NO_COLUMN ) ;
2008-12-10 05:42:49 +01:00
}
return c ;
}
const char * Db : : AssertValue ( PGresult * r , int row , int col )
{
const char * res = PQgetvalue ( r , row , col ) ;
if ( ! res )
{
log < < log1 < < " Db: there is no such an item in the result, row: " < < row < < " , col: " < < col < < logend ;
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_NO_ITEM ) ;
2008-12-10 05:42:49 +01:00
}
return res ;
}
2008-12-14 06:28:28 +01:00
2008-12-10 05:42:49 +01:00
void Db : : ClearResult ( PGresult * r )
{
if ( r )
PQclear ( r ) ;
}
bool Db : : CheckUser ( std : : string & login , std : : string & password , long & user_id )
{
PGresult * r = 0 ;
bool user_ok = false ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select id from core.user where login=' " < < Escape ( login ) < < " ' and password=' " < < Escape ( password ) < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
if ( rows = = 0 )
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_DB_INCORRECT_LOGIN ) ;
2008-12-10 05:42:49 +01:00
if ( rows > 1 )
{
log < < log1 < < " Db: there is more than one user: " < < login < < " (with the same password) " < < logend ;
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_DB_MORE_THAN_ONE_LOGIN ) ;
2008-12-10 05:42:49 +01:00
}
int cuser_id = AssertColumn ( r , " id " ) ;
const char * fuser_id = AssertValue ( r , 0 , cuser_id ) ;
user_id = atol ( fuser_id ) ;
user_ok = true ;
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
return user_ok ;
}
2010-02-28 01:08:10 +01:00
Error Db : : AddUser ( User & user , const std : : string & password )
{
PGresult * r = 0 ;
Error status = WINIX_ERR_OK ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " insert into core.user (login, password, super_user, email, cms_notify, thread_notify) values ( " ;
query < < ' \' ' < < Escape ( user . name ) < < " ', " ;
query < < ' \' ' < < Escape ( password ) < < " ', " ;
query < < ' \' ' < < static_cast < int > ( user . super_user ) < < " ', " ;
query < < ' \' ' < < Escape ( user . email ) < < " ', " ;
query < < ' \' ' < < user . cms_notify < < " ', " ;
query < < ' \' ' < < user . thread_notify < < " '); " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
user . id = AssertCurrval ( " core.user_id_seq " ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
2008-12-10 05:42:49 +01:00
2010-03-15 02:47:26 +01:00
//!! wywalic z nazwy 'Subject' nic nie jest robione z tytulem
// ta metoda uzywana tez jest w EditParentUrlById()
2008-12-10 05:42:49 +01:00
bool Db : : AddItemCreateUrlSubject ( Item & item )
{
bool is_that_url ;
PGresult * r = 0 ;
int index = 1 ;
const int max_index = 100 ;
char appendix [ 20 ] ;
appendix [ 0 ] = 0 ;
try
{
do
{
std : : ostringstream query ;
// this Escape can be put at the beginning (performance)
2008-12-14 06:28:28 +01:00
query < < " select id from core.item where url=' " < < Escape ( item . url ) < < appendix < < " ' and parent_id=' " < < item . parent_id < < " '; " ;
2008-12-10 05:42:49 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
if ( PQntuples ( r ) ! = 0 )
{
sprintf ( appendix , " _(%d) " , + + index ) ;
is_that_url = true ;
}
else
{
2008-12-14 06:28:28 +01:00
item . url + = appendix ;
2008-12-10 05:42:49 +01:00
is_that_url = false ;
}
ClearResult ( r ) ;
r = 0 ;
}
while ( is_that_url & & index < = max_index ) ;
}
catch ( const Error & )
{
is_that_url = true ; // for return false
}
ClearResult ( r ) ;
return ! is_that_url ;
}
// for testing consistency
void Db : : CheckAllUrlSubjectModifyItem ( Item & item )
{
PGresult * r = 0 ;
try
{
std : : ostringstream query ;
2008-12-14 06:28:28 +01:00
query < < " update core.item set url= " ;
2008-12-10 05:42:49 +01:00
2008-12-14 06:28:28 +01:00
// url
2008-12-10 05:42:49 +01:00
if ( AddItemCreateUrlSubject ( item ) )
2008-12-14 06:28:28 +01:00
query < < ' \' ' < < Escape ( item . url ) < < ' \' ' ;
2008-12-10 05:42:49 +01:00
else
{
query < < ' \' ' < < item . id < < ' \' ' ;
2008-12-14 06:28:28 +01:00
item . url . clear ( ) ;
2008-12-10 05:42:49 +01:00
}
query < < " where id=' " < < item . id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
}
// for checking consistency
void Db : : CheckAllUrlSubject ( )
{
PGresult * r = 0 ;
Item item ;
try
{
AssertConnection ( ) ;
std : : ostringstream query , query2 ;
2009-06-05 22:29:06 +02:00
// !! subject zostal wrzucony do tabeli item
2008-12-14 06:28:28 +01:00
query < < " select item.id, subject from core.item left join core.content on item.content_id = content.id where url is null or url='' " ;
2008-12-10 05:42:49 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
int cid = AssertColumn ( r , " id " ) ;
int csubject = AssertColumn ( r , " subject " ) ;
for ( int i = 0 ; i < rows ; + + i )
{
2008-12-14 06:28:28 +01:00
item . id = atol ( AssertValue ( r , i , cid ) ) ;
2008-12-10 05:42:49 +01:00
item . subject = AssertValue ( r , i , csubject ) ;
CheckAllUrlSubjectModifyItem ( item ) ;
}
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
}
long Db : : AssertCurrval ( const char * table )
{
PGresult * r ;
std : : ostringstream query ;
query < < " select currval(' " < < table < < " '); " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
if ( PQntuples ( r ) ! = 1 )
{
log < < log1 < < " Db: error (currval) for table: " < < table < < " , " < < PQerrorMessage ( pg_conn ) < < logend ;
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_DB_ERR_CURRVAL ) ;
2008-12-10 05:42:49 +01:00
}
long res = strtol ( AssertValue ( r , 0 , 0 ) , 0 , 10 ) ;
return res ;
}
2008-12-14 06:28:28 +01:00
Error Db : : AddItemIntoItem ( Item & item )
2008-12-10 05:42:49 +01:00
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-10 05:42:49 +01:00
bool url_without_id = false ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2010-06-22 23:09:37 +02:00
query < < " insert into core.item (user_id, modification_user_id, group_id, privileges, date_creation, date_modification, type, "
2010-03-15 02:47:26 +01:00
" parent_id, content_id, auth, auth_path, default_item, subject, guest_name, url) values ( " ;
2009-06-05 22:29:06 +02:00
query < < ' \' ' < < item . user_id < < " ', " ;
2010-06-22 23:09:37 +02:00
query < < ' \' ' < < item . modification_user_id < < " ', " ;
2009-06-05 22:29:06 +02:00
query < < ' \' ' < < item . group_id < < " ', " ;
query < < ' \' ' < < item . privileges < < " ', " ;
query < < ' \' ' < < ConvertTime ( item . date_creation ) < < " ', " ;
2009-03-23 00:54:15 +01:00
query < < ' \' ' < < ConvertTime ( item . date_modification ) < < " ', " ;
2009-06-05 22:29:06 +02:00
query < < ' \' ' < < static_cast < int > ( item . type ) < < " ', " ;
query < < ' \' ' < < item . parent_id < < " ', " ;
query < < ' \' ' < < item . content_id < < " ', " ;
2010-03-15 02:47:26 +01:00
query < < ' \' ' < < static_cast < int > ( item . auth ) < < " ', " ;
query < < ' \' ' < < Escape ( item . auth_path ) < < " ', " ;
2009-06-05 22:29:06 +02:00
query < < ' \' ' < < item . default_item < < " ', " ;
query < < ' \' ' < < Escape ( item . subject ) < < " ', " ;
2009-06-07 04:40:27 +02:00
query < < ' \' ' < < Escape ( item . guest_name ) < < " ', " ;
2009-12-30 21:46:12 +01:00
2008-12-10 05:42:49 +01:00
url_without_id = AddItemCreateUrlSubject ( item ) ;
if ( url_without_id )
2008-12-14 06:28:28 +01:00
query < < ' \' ' < < Escape ( item . url ) < < " '); " ;
2008-12-10 05:42:49 +01:00
else
2008-12-14 06:28:28 +01:00
query < < " currval('core.item_id_seq') " < < " ); " ;
2008-12-10 05:42:49 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
item . id = AssertCurrval ( " core.item_id_seq " ) ;
if ( ! url_without_id )
2008-12-14 06:28:28 +01:00
ToString ( item . url , item . id ) ;
2008-12-10 05:42:49 +01:00
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2008-12-14 06:28:28 +01:00
Error Db : : AddItemIntoContent ( Item & item )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-14 06:28:28 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2009-06-05 22:29:06 +02:00
query < < " insert into core.content (content, content_type) values ( " ;
2010-01-11 15:47:52 +01:00
query < < ' \' ' < < Escape ( item . content ) < < " ', " ;
query < < ' \' ' < < static_cast < int > ( item . content_type ) < < " '); " ;
2008-12-14 06:28:28 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
item . content_id = AssertCurrval ( " core.content_id_seq " ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
Error Db : : AddItem ( Item & item )
{
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-14 06:28:28 +01:00
2008-12-31 14:36:46 +01:00
if ( item . type = = Item : : file )
result = AddItemIntoContent ( item ) ;
else
item . content_id = - 1 ;
2010-02-28 01:08:10 +01:00
if ( result = = WINIX_ERR_OK )
2008-12-14 06:28:28 +01:00
result = AddItemIntoItem ( item ) ;
return result ;
}
2009-06-05 22:29:06 +02:00
Error Db : : EditItemInItem ( Item & item , bool with_url )
2008-12-10 05:42:49 +01:00
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-10 05:42:49 +01:00
bool url_without_id = false ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2010-06-22 23:09:37 +02:00
query < < " update core.item set (user_id, modification_user_id, group_id, privileges, date_creation, date_modification, type, "
2010-03-15 02:47:26 +01:00
" default_item, parent_id, subject, guest_name, auth, auth_path " ;
2008-12-10 05:42:49 +01:00
2009-06-05 22:29:06 +02:00
if ( with_url )
2008-12-21 22:17:09 +01:00
query < < " , url " ;
2008-12-10 05:42:49 +01:00
2008-12-14 06:28:28 +01:00
query < < " ) = ( " ;
2009-06-05 22:29:06 +02:00
query < < ' \' ' < < item . user_id < < " ', " ;
2010-06-22 23:09:37 +02:00
query < < ' \' ' < < item . modification_user_id < < " ', " ;
2009-06-05 22:29:06 +02:00
query < < ' \' ' < < item . group_id < < " ', " ;
query < < ' \' ' < < item . privileges < < " ', " ;
query < < ' \' ' < < ConvertTime ( item . date_creation ) < < " ', " ;
2009-03-23 00:54:15 +01:00
query < < ' \' ' < < ConvertTime ( item . date_modification ) < < " ', " ;
2009-06-05 22:29:06 +02:00
query < < ' \' ' < < static_cast < int > ( item . type ) < < " ', " ;
query < < ' \' ' < < item . default_item < < " ', " ;
query < < ' \' ' < < item . parent_id < < " ', " ;
2009-06-07 04:40:27 +02:00
query < < ' \' ' < < Escape ( item . subject ) < < " ', " ;
2009-12-30 21:46:12 +01:00
query < < ' \' ' < < Escape ( item . guest_name ) < < " ', " ;
2010-03-15 02:47:26 +01:00
query < < ' \' ' < < static_cast < int > ( item . auth ) < < " ', " ;
query < < ' \' ' < < Escape ( item . auth_path ) < < " ' " ;
2008-12-10 05:42:49 +01:00
2009-06-05 22:29:06 +02:00
if ( with_url )
2008-12-10 05:42:49 +01:00
{
url_without_id = AddItemCreateUrlSubject ( item ) ;
if ( url_without_id )
2008-12-14 06:28:28 +01:00
query < < " , ' " < < Escape ( item . url ) < < " ' " ;
2008-12-10 05:42:49 +01:00
else
2008-12-14 06:28:28 +01:00
query < < " , ' " < < item . id < < " ' " ;
2008-12-10 05:42:49 +01:00
}
query < < " ) where id=' " < < item . id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
2009-06-05 22:29:06 +02:00
if ( with_url & & ! url_without_id )
2008-12-14 06:28:28 +01:00
ToString ( item . url , item . id ) ;
2008-12-10 05:42:49 +01:00
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2008-12-14 06:28:28 +01:00
Error Db : : EditItemInContent ( Item & item )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-14 06:28:28 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2009-06-05 22:29:06 +02:00
query < < " update core.content set (content, content_type) = ( " ;
2008-12-14 06:28:28 +01:00
2010-01-11 15:47:52 +01:00
query < < ' \' ' < < Escape ( item . content ) < < " ', " ;
query < < ' \' ' < < static_cast < int > ( item . content_type ) < < " ' " ;
2008-12-14 06:28:28 +01:00
query < < " ) where id=' " < < item . content_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2008-12-21 22:17:09 +01:00
Error Db : : EditItemGetId ( Item & item )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-21 22:17:09 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select item.id, content.id from core.item left join core.content on item.content_id = content.id where item.parent_id=' " ;
query < < item . parent_id < < " ' and item.url=' " < < Escape ( item . url ) < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
if ( PQntuples ( r ) ! = 1 | | PQnfields ( r ) ! = 2 )
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_NO_ITEM ) ;
2008-12-21 22:17:09 +01:00
// we cannot use AssertColumn() with a name because both columns are called 'id'
item . id = atol ( AssertValue ( r , 0 , 0 ) ) ;
item . content_id = atol ( AssertValue ( r , 0 , 1 ) ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2008-12-14 06:28:28 +01:00
2008-12-21 22:17:09 +01:00
Error Db : : EditItemGetContentId ( Item & item )
2008-12-14 06:28:28 +01:00
{
2008-12-21 22:17:09 +01:00
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-21 22:17:09 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2008-12-31 19:28:12 +01:00
// !! tutaj chyba nie ma potrzeby robic left join z core.content (nie uzywamy nic z tamtej tabeli)
2008-12-21 22:17:09 +01:00
query < < " select content_id from core.item left join core.content on item.content_id = content.id where item.id=' " ;
query < < item . id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
if ( PQntuples ( r ) ! = 1 | | PQnfields ( r ) ! = 1 )
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_NO_ITEM ) ;
2008-12-14 06:28:28 +01:00
2008-12-21 22:17:09 +01:00
item . content_id = atol ( AssertValue ( r , 0 , 0 ) ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
// item.id must be set
2008-12-30 02:05:03 +01:00
// !! moze nazwa poprostu EditItem (nie trzeba tego ById) ? (sprawdzic czy nie koliduje z inna nazwa)
2009-06-05 22:29:06 +02:00
Error Db : : EditItemById ( Item & item , bool with_url )
2008-12-21 22:17:09 +01:00
{
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-31 19:28:12 +01:00
// !! dla katalogow nie testowane jeszcze
if ( item . type = = Item : : file )
result = EditItemGetContentId ( item ) ;
2008-12-21 22:17:09 +01:00
2010-02-28 01:08:10 +01:00
if ( result = = WINIX_ERR_OK )
2008-12-21 22:17:09 +01:00
{
2008-12-31 19:28:12 +01:00
if ( item . type = = Item : : file )
result = EditItemInContent ( item ) ;
2008-12-14 06:28:28 +01:00
2010-02-28 01:08:10 +01:00
if ( result = = WINIX_ERR_OK )
2009-06-05 22:29:06 +02:00
result = EditItemInItem ( item , with_url ) ;
2008-12-21 22:17:09 +01:00
}
return result ;
}
// item.url and item.parent_id must be set
2008-12-31 19:28:12 +01:00
// doesn't work with directiories
2009-06-05 22:29:06 +02:00
Error Db : : EditItemByUrl ( Item & item , bool with_url )
2008-12-21 22:17:09 +01:00
{
Error result = EditItemGetId ( item ) ;
2010-02-28 01:08:10 +01:00
if ( result = = WINIX_ERR_OK )
2008-12-21 22:17:09 +01:00
{
result = EditItemInContent ( item ) ;
2010-02-28 01:08:10 +01:00
if ( result = = WINIX_ERR_OK )
2009-06-05 22:29:06 +02:00
result = EditItemInItem ( item , with_url ) ;
2008-12-21 22:17:09 +01:00
}
2008-12-14 06:28:28 +01:00
return result ;
}
2008-12-31 19:28:12 +01:00
Error Db : : EditDefaultItem ( long id , long new_default_item )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-31 19:28:12 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " update core.item set (default_item) = (' " < < new_default_item < < " ') where id=' " < < id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
char * rows_str = PQcmdTuples ( r ) ;
long rows = 0 ;
if ( rows_str )
rows = atol ( rows_str ) ;
if ( rows = = 0 )
{
2010-02-28 01:08:10 +01:00
result = WINIX_ERR_NO_ITEM ;
2008-12-31 19:28:12 +01:00
log < < log1 < < " Db: EditDefaultItem: no such item, id: " < < id < < logend ;
}
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2008-12-14 06:28:28 +01:00
2008-12-21 22:17:09 +01:00
2010-07-27 22:41:56 +02:00
PGresult * Db : : GetItemsQuery ( const ItemQuery & iq , bool skip_other_sel )
2008-12-10 05:42:49 +01:00
{
std : : ostringstream query ;
2010-02-22 23:52:09 +01:00
query < < " select item.id " ;
2010-07-27 22:41:56 +02:00
if ( ! skip_other_sel )
{
if ( iq . sel_parent_id ) query < < " ,parent_id " ;
if ( iq . sel_user_id ) query < < " ,user_id, modification_user_id " ;
if ( iq . sel_group_id ) query < < " ,group_id " ;
if ( iq . sel_guest_name ) query < < " ,guest_name " ;
if ( iq . sel_privileges ) query < < " ,privileges " ;
if ( iq . sel_date ) query < < " ,date_creation, date_modification " ;
if ( iq . sel_subject ) query < < " ,subject " ;
if ( iq . sel_content ) query < < " ,content, content_type, content_id " ;
if ( iq . sel_url ) query < < " ,url " ;
if ( iq . sel_type ) query < < " ,type " ;
if ( iq . sel_default_item ) query < < " ,default_item " ;
if ( iq . sel_auth ) query < < " ,auth, auth_path " ;
}
2009-06-05 22:29:06 +02:00
query < < " from core.item " ;
2008-12-10 05:42:49 +01:00
2010-02-22 23:52:09 +01:00
if ( iq . sel_content ) query < < " left join core.content on item.content_id = content.id " ;
if ( iq . where_id | | iq . where_parent_id | | iq . where_type | | iq . where_auth )
{
query < < " where " ;
const char * add_and = " and " ;
const char * if_and = " " ;
if ( iq . where_id ) { query < < if_and < < " id=' " < < iq . id < < " ' " ; if_and = add_and ; }
if ( iq . where_parent_id ) { query < < if_and < < " parent_id=' " < < iq . parent_id < < " ' " ; if_and = add_and ; }
if ( iq . where_type ) { query < < if_and < < " type=' " < < static_cast < int > ( iq . type ) < < " ' " ; if_and = add_and ; }
2010-03-15 02:47:26 +01:00
if ( iq . where_auth )
{
query < < if_and < < " auth " ;
if ( iq . auth_equal )
query < < " = " ;
else
query < < " != " ;
query < < " ' " < < static_cast < int > ( iq . auth ) < < " ' " ;
if_and = add_and ;
}
2010-02-22 23:52:09 +01:00
}
2008-12-10 05:42:49 +01:00
2009-06-05 22:29:06 +02:00
query < < " order by item.date_creation " ;
2009-04-21 01:49:28 +02:00
2010-02-22 23:52:09 +01:00
if ( iq . sort_asc )
query < < " asc; " ;
2009-04-21 01:49:28 +02:00
else
2010-02-22 23:52:09 +01:00
query < < " desc; " ;
2009-04-21 01:49:28 +02:00
2008-12-10 05:42:49 +01:00
return AssertQuery ( query . str ( ) ) ;
}
2010-02-22 23:52:09 +01:00
2010-08-10 22:43:38 +02:00
void Db : : GetItems ( std : : vector < Item > & item_tab , const ItemQuery & item_query )
2008-12-10 05:42:49 +01:00
{
2010-08-10 22:43:38 +02:00
item_tab . clear ( ) ;
2008-12-10 05:42:49 +01:00
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
2010-02-22 23:52:09 +01:00
r = GetItemsQuery ( item_query ) ;
2008-12-10 05:42:49 +01:00
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
Item item ;
int rows = PQntuples ( r ) ;
ItemColumns col ;
col . SetColumns ( r ) ;
for ( int i = 0 ; i < rows ; + + i )
{
col . SetItem ( r , i , item ) ;
2010-08-10 22:43:38 +02:00
item_tab . push_back ( item ) ;
2008-12-10 05:42:49 +01:00
}
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
}
2010-07-27 22:41:56 +02:00
2010-08-10 22:43:38 +02:00
void Db : : GetItems ( std : : vector < long > & item_tab , const ItemQuery & item_query )
2010-07-27 22:41:56 +02:00
{
2010-08-10 22:43:38 +02:00
item_tab . clear ( ) ;
2010-07-27 22:41:56 +02:00
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
r = GetItemsQuery ( item_query , true ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
for ( int i = 0 ; i < rows ; + + i )
{
long id = atol ( AssertValue ( r , i , 0 ) ) ;
2010-08-10 22:43:38 +02:00
item_tab . push_back ( id ) ;
2010-07-27 22:41:56 +02:00
}
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
}
2009-11-18 02:58:38 +01:00
// how many items there are in a 'parent_id' directory
long Db : : Size ( long parent_id , Item : : Type type )
{
PGresult * r = 0 ;
int res = 0 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select count(id) from core.item where " ;
if ( type ! = Item : : none )
query < < " type=' " < < ( int ) type < < " ' and " ;
query < < " parent_id=' " < < parent_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
res = atol ( AssertValue ( r , 0 , 0 ) ) ;
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
return res ;
}
2010-02-16 01:37:00 +01:00
// !! zamienic nazwe na GetFile?
// !! cos tu pomyslec innego, ta metoda nie musi pobierac tablicy za argument
// i tak istnieje tylko jedna pozycja o okreslonym id
// mozna zwracac bool i pobierac referencje na item
2010-08-10 22:43:38 +02:00
void Db : : GetItem ( std : : vector < Item > & item_tab , long id )
2008-12-10 05:42:49 +01:00
{
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2008-12-14 06:28:28 +01:00
query < < " select * from core.item left join core.content on item.content_id = content.id where type='1' and item.id=' " < < id < < " '; " ;
2008-12-10 05:42:49 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
Item item ;
int rows = PQntuples ( r ) ;
if ( rows > 1 )
log < < log1 < < " Db: we have more than one item with id: " < < id < < logend ;
ItemColumns col ;
col . SetColumns ( r ) ;
for ( int i = 0 ; i < rows ; + + i )
{
col . SetItem ( r , i , item ) ;
2010-08-10 22:43:38 +02:00
item_tab . push_back ( item ) ;
2008-12-10 05:42:49 +01:00
}
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
}
2008-12-14 06:28:28 +01:00
2008-12-30 02:05:03 +01:00
// !! nowy interfejs
Error Db : : GetItem ( long parent_id , const std : : string & url , Item & item )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-30 02:05:03 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select * from core.item left join core.content on item.content_id = content.id where type='1' and item.parent_id=' " ;
query < < parent_id < < " ' and item.url=' " < < Escape ( url ) < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
if ( rows = = 0 )
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_NO_ITEM ) ;
2008-12-30 02:05:03 +01:00
ItemColumns col ;
col . SetColumns ( r ) ;
col . SetItem ( r , 0 , item ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2010-01-25 05:52:17 +01:00
Error Db : : GetItemById ( long item_id , Item & item )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2010-01-25 05:52:17 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select * from core.item left join core.content on item.content_id = content.id where item.id=' " < < item_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
if ( rows = = 0 )
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_NO_ITEM ) ;
2010-01-25 05:52:17 +01:00
ItemColumns col ;
col . SetColumns ( r ) ;
col . SetItem ( r , 0 , item ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2008-12-30 02:05:03 +01:00
2008-12-31 19:28:12 +01:00
long Db : : GetItemId ( long parent_id , const std : : string & url , Item : : Type type )
{
PGresult * r = 0 ;
long result = - 1 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select id from core.item where type=' " < < static_cast < int > ( type ) < < " ' and item.parent_id=' " ;
query < < parent_id < < " ' and item.url=' " < < Escape ( url ) < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
if ( rows = = 1 )
result = atol ( AssertValue ( r , 0 , 0 ) ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
long Db : : GetFileId ( long parent_id , const std : : string & url )
{
return GetItemId ( parent_id , url , Item : : file ) ;
}
long Db : : GetDirId ( long parent_id , const std : : string & url )
{
return GetItemId ( parent_id , url , Item : : dir ) ;
}
2008-12-21 22:17:09 +01:00
bool Db : : GetPriv ( Item & item , long id )
{
bool result = false ;
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2010-06-22 23:09:37 +02:00
query < < " select user_id, modification_user_id, group_id, privileges, guest_name from core.item "
2010-02-16 01:37:00 +01:00
< < " where item.id=' " < < id < < " '; " ;
2008-12-21 22:17:09 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
if ( rows ! = 1 )
throw Error ( ) ;
ItemColumns col ;
col . SetColumns ( r ) ;
col . SetItem ( r , 0 , item ) ;
result = true ;
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
return result ;
}
2008-12-30 02:05:03 +01:00
// !! to jest nowy interfejs, z jawnym podaniem id
Error Db : : EditPrivById ( Item & item , long id )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-30 02:05:03 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2010-06-22 23:09:37 +02:00
query < < " update core.item set (user_id, modification_user_id, group_id, privileges, guest_name) = ( " ;
2008-12-30 02:05:03 +01:00
query < < ' \' ' < < item . user_id < < " ', " ;
2010-06-22 23:09:37 +02:00
query < < ' \' ' < < item . modification_user_id < < " ', " ;
2008-12-30 02:05:03 +01:00
query < < ' \' ' < < item . group_id < < " ', " ;
2009-06-07 04:40:27 +02:00
query < < ' \' ' < < item . privileges < < " ', " ;
query < < ' \' ' < < Escape ( item . guest_name ) < < " ' " ;
2008-12-30 02:05:03 +01:00
query < < " ) where id=' " < < id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2008-12-21 22:17:09 +01:00
2010-02-16 01:37:00 +01:00
2010-03-15 02:47:26 +01:00
Error Db : : EditParentUrlById ( Item & item , long id )
{
PGresult * r = 0 ;
Error result = WINIX_ERR_OK ;
bool url_without_id = false ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " update core.item set (parent_id, url) = ( " ;
query < < ' \' ' < < item . parent_id < < " ', " ;
url_without_id = AddItemCreateUrlSubject ( item ) ;
if ( url_without_id )
query < < ' \' ' < < Escape ( item . url ) < < " ' " ;
else
query < < ' \' ' < < item . id < < " ' " ; ;
query < < " ) where id=' " < < id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
Error Db : : EditAuthById ( Item & item , long id )
{
PGresult * r = 0 ;
Error result = WINIX_ERR_OK ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " update core.item set (auth, auth_path) = ( " ;
query < < ' \' ' < < static_cast < int > ( item . auth ) < < " ', " ;
query < < ' \' ' < < Escape ( item . auth_path ) < < " ') " ;
query < < " where id=' " < < id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2009-02-06 14:12:03 +01:00
Error Db : : DelDirById ( long id )
{
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2009-02-06 14:12:03 +01:00
PGresult * r = 0 ;
const char * crows ;
try
{
AssertConnection ( ) ;
std : : ostringstream query , query2 ;
2010-02-06 15:08:44 +01:00
// !! trzeba poprawic to usuwanie gdy beda hard linki
2009-02-06 14:12:03 +01:00
query < < " delete from core.content where content.id in (select content_id from core.item where parent_id=' " < < id < < " '); " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
crows = PQcmdTuples ( r ) ;
if ( crows )
log < < log2 < < " Db: deleted " < < atol ( crows ) < < " rows from core.content " < < logend ;
query2 < < " delete from core.item where id=' " < < id < < " ' or parent_id=' " < < id < < " '; " ;
r = AssertQuery ( query2 . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
crows = PQcmdTuples ( r ) ;
if ( crows )
log < < log1 < < " Db: deleted dir: " < < id < < " (deleted: " < < atol ( crows ) < < " rows) " < < logend ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2010-05-20 20:28:19 +02:00
Error Db : : EditSubjectById ( Item & item , long id )
{
PGresult * r = 0 ;
Error result = WINIX_ERR_OK ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " update core.item set (subject) = ( " ;
query < < ' \' ' < < Escape ( item . subject ) < < " ') " ;
query < < " where id=' " < < id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
2008-12-14 06:28:28 +01:00
bool Db : : DelItemDelItem ( const Item & item )
2008-12-10 05:42:49 +01:00
{
2008-12-14 06:28:28 +01:00
long rows = 0 ;
2008-12-10 05:42:49 +01:00
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2008-12-14 06:28:28 +01:00
query < < " delete from core.item where id=' " < < item . id < < " '; " ;
2008-12-10 05:42:49 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
const char * crows = PQcmdTuples ( r ) ;
if ( crows )
{
rows = atol ( crows ) ;
if ( rows > 1 )
log < < log1 < < " Db: more than one item were deleted " < < logend ;
2008-12-14 06:28:28 +01:00
else
if ( rows = = 0 )
log < < log1 < < " Db: no item has been deleted " < < logend ;
2008-12-10 05:42:49 +01:00
}
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
return rows ! = 0 ;
}
2008-12-14 06:28:28 +01:00
void Db : : DelItemDelContent ( const Item & item )
{
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " delete from core.content where id=' " < < item . content_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
const char * crows = PQcmdTuples ( r ) ;
if ( crows )
{
long rows = atol ( crows ) ;
if ( rows > 1 )
log < < log1 < < " Db: more than one content were deleted " < < logend ;
else
if ( rows = = 0 )
log < < log1 < < " Db: no content has been deleted " < < logend ;
}
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
}
Error Db : : DelItemCountContents ( const Item & item , long & contents )
{
2010-02-28 01:08:10 +01:00
Error result = WINIX_ERR_OK ;
2008-12-14 06:28:28 +01:00
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select count('id') from core.item where content_id=' " < < item . content_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
contents = atol ( AssertValue ( r , 0 , 0 ) ) ;
}
catch ( const Error & e )
{
result = e ;
}
ClearResult ( r ) ;
return result ;
}
bool Db : : DelItem ( const Item & item )
{
long contents ;
Error result = DelItemCountContents ( item , contents ) ;
2010-02-28 01:08:10 +01:00
if ( result = = WINIX_ERR_OK & & contents = = 1 )
2008-12-14 06:28:28 +01:00
DelItemDelContent ( item ) ;
return DelItemDelItem ( item ) ;
}
2010-08-10 22:43:38 +02:00
void Db : : GetDirs ( DirContainer & dir_tab )
2008-12-10 05:42:49 +01:00
{
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2008-12-22 17:03:03 +01:00
query < < " select * from core.item where type='0'; " ;
2008-12-10 05:42:49 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
Item item ;
int rows = PQntuples ( r ) ;
ItemColumns col ;
col . SetColumns ( r ) ;
for ( int i = 0 ; i < rows ; + + i )
{
col . SetItem ( r , i , item ) ;
2010-08-10 22:43:38 +02:00
dir_tab . PushBack ( item ) ;
2008-12-10 05:42:49 +01:00
}
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
}
2010-08-10 22:43:38 +02:00
void Db : : GetUsers ( UGContainer < User > & user_tab )
2008-12-21 22:17:09 +01:00
{
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2009-10-01 00:31:20 +02:00
query < < " select id, login, super_user, group_id, email, cms_notify, thread_notify from core.user left outer join core.group_mem on core.user.id = core.group_mem.user_id order by id asc; " ;
2008-12-21 22:17:09 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
int cid = AssertColumn ( r , " id " ) ;
int cname = AssertColumn ( r , " login " ) ;
int csuper_user = AssertColumn ( r , " super_user " ) ;
int cgroup_id = AssertColumn ( r , " group_id " ) ;
2009-10-01 00:31:20 +02:00
int cemail = AssertColumn ( r , " email " ) ;
int ccms_notify = AssertColumn ( r , " cms_notify " ) ;
int cthread_notify = AssertColumn ( r , " thread_notify " ) ;
2008-12-21 22:17:09 +01:00
User u ;
long last_id = - 1 ;
2010-08-10 22:43:38 +02:00
UGContainer < User > : : Iterator iter = user_tab . End ( ) ;
2008-12-21 22:17:09 +01:00
for ( int i = 0 ; i < rows ; + + i )
{
u . id = atol ( AssertValue ( r , i , cid ) ) ;
if ( u . id ! = last_id )
{
u . name = AssertValue ( r , i , cname ) ;
u . super_user = static_cast < bool > ( atoi ( AssertValue ( r , i , csuper_user ) ) ) ;
2009-10-01 00:31:20 +02:00
u . email = AssertValue ( r , i , cemail ) ;
u . cms_notify = atoi ( AssertValue ( r , i , ccms_notify ) ) ;
u . thread_notify = atoi ( AssertValue ( r , i , cthread_notify ) ) ;
2008-12-21 22:17:09 +01:00
log < < log1 < < " Db: get user: id: " < < u . id < < " , name: " < < u . name < < " , super_user: " < < u . super_user < < logend ;
2010-08-10 22:43:38 +02:00
iter = user_tab . PushBack ( u ) ;
2010-02-28 01:08:10 +01:00
2010-08-10 22:43:38 +02:00
if ( iter = = user_tab . End ( ) )
2010-02-28 01:08:10 +01:00
log < < log1 < < " Db: can't add a user: " < < u . name < < logend ;
2008-12-21 22:17:09 +01:00
last_id = u . id ;
}
long group_id = atol ( AssertValue ( r , i , cgroup_id ) ) ;
2010-08-10 22:43:38 +02:00
if ( ! PQgetisnull ( r , i , cgroup_id ) & & group_id ! = - 1 & & iter ! = user_tab . End ( ) )
2008-12-21 22:17:09 +01:00
{
iter - > groups . push_back ( group_id ) ;
log < < log3 < < " Db: user: " < < iter - > name < < " is a member of group_id: " < < group_id < < logend ;
}
}
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
}
2010-08-10 22:43:38 +02:00
void Db : : GetGroups ( UGContainer < Group > & group_tab )
2008-12-21 22:17:09 +01:00
{
PGresult * r = 0 ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select id, core.group.group, user_id from core.group left outer join core.group_mem on core.group.id = core.group_mem.group_id order by id asc; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
int cid = AssertColumn ( r , " id " ) ;
int cname = AssertColumn ( r , " group " ) ;
int cuser_id = AssertColumn ( r , " user_id " ) ;
Group g ;
long last_id = - 1 ;
UGContainer < Group > : : Iterator iter ;
for ( int i = 0 ; i < rows ; + + i )
{
g . id = atol ( AssertValue ( r , i , cid ) ) ;
if ( g . id ! = last_id )
{
g . name = AssertValue ( r , i , cname ) ;
log < < log3 < < " Db: get group, id: " < < g . id < < " , group: " < < g . name < < logend ;
2010-08-10 22:43:38 +02:00
iter = group_tab . PushBack ( g ) ;
2008-12-21 22:17:09 +01:00
last_id = g . id ;
}
long user_id = atol ( AssertValue ( r , i , cuser_id ) ) ;
2010-08-10 22:43:38 +02:00
if ( ! PQgetisnull ( r , i , cuser_id ) & & user_id ! = - 1 & & ! group_tab . Empty ( ) )
2008-12-21 22:17:09 +01:00
{
iter - > members . push_back ( user_id ) ;
log < < log3 < < " Db: get group member: user_id: " < < user_id < < logend ;
}
}
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
}
2008-12-10 05:42:49 +01:00
2009-01-26 21:49:28 +01:00
tm Db : : ConvertTime ( const char * str )
{
tm t ;
memset ( & t , 0 , sizeof ( t ) ) ;
if ( ! str )
return t ;
size_t len = strlen ( str ) ;
if ( len ! = 19 )
{
// unknown format
// the format must be like this: 2008-12-31 22:30:00
return t ;
}
t . tm_year = atoi ( str + 0 ) - 1900 ; /* year - 1900 */
t . tm_mon = atoi ( str + 5 ) - 1 ; /* month of year (0 - 11) */
t . tm_mday = atoi ( str + 8 ) ; /* day of month (1 - 31) */
t . tm_hour = atoi ( str + 11 ) ; /* hours (0 - 23) */
t . tm_min = atoi ( str + 14 ) ; /* minutes (0 - 59) */
t . tm_sec = atoi ( str + 17 ) ; /* seconds (0 - 60) */
// t.tm_wday = 0; /* day of week (Sunday = 0) */
// t.tm_yday = 0; /* day of year (0 - 365) */
// t.tm_isdst = 0; /* is summer time in effect? */
// t.tm_zone = 0; // const_cast<char*>(""); /* abbreviation of timezone name */
//return mktime(&t);
return t ;
}
2008-12-10 05:42:49 +01:00
2009-03-23 00:54:15 +01:00
const char * Db : : ConvertTime ( const tm & t )
{
// not thread safe
static char buffer [ 100 ] ;
sprintf ( buffer , " %04d-%02d-%02d %02d:%02d:%02d " , t . tm_year + 1900 , t . tm_mon + 1 , t . tm_mday , t . tm_hour , t . tm_min , t . tm_sec ) ;
return buffer ;
}
2008-12-10 05:42:49 +01:00
2009-04-21 01:49:28 +02:00
Error Db : : GetThreadByDirId ( long dir_id , Thread & thread )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2009-04-21 01:49:28 +02:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2010-01-25 05:52:17 +01:00
query < < " select thread.id, thread.parent_id, thread.dir_id, thread.closed, thread.items, "
" thread.last_item, item.date_modification, item.user_id "
" from core.thread left join core.item on thread.last_item = item.id "
" where thread.dir_id = ' " < < dir_id < < " '; " ;
2009-04-21 01:49:28 +02:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
if ( rows > 1 )
log < < log1 < < " Db: there is more than one thread with dir_id: " < < dir_id < < logend ;
else
if ( rows = = 0 )
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_NO_THREAD ) ;
2009-04-21 01:49:28 +02:00
2009-06-05 22:29:06 +02:00
int cid = AssertColumn ( r , " id " ) ;
int cparent_id = AssertColumn ( r , " parent_id " ) ;
int cdir_id = AssertColumn ( r , " dir_id " ) ;
int cclosed = AssertColumn ( r , " closed " ) ;
int citems = AssertColumn ( r , " items " ) ;
int clast_item = AssertColumn ( r , " last_item " ) ;
int cdate_modification = PQfnumber ( r , " date_modification " ) ;
int cuser_id = PQfnumber ( r , " user_id " ) ;
thread . id = atol ( AssertValue ( r , 0 , cid ) ) ;
thread . parent_id = atol ( AssertValue ( r , 0 , cparent_id ) ) ;
thread . dir_id = atol ( AssertValue ( r , 0 , cdir_id ) ) ;
thread . closed = atol ( AssertValue ( r , 0 , cclosed ) ) = = 0 ? false : true ;
thread . items = atol ( AssertValue ( r , 0 , citems ) ) ;
thread . last_item . id = atol ( AssertValue ( r , 0 , clast_item ) ) ;
thread . last_item . date_modification = ConvertTime ( Db : : AssertValue ( r , 0 , cdate_modification ) ) ;
thread . last_item . user_id = atol ( Db : : AssertValue ( r , 0 , cuser_id ) ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
Error Db : : GetThreads ( long parent_id , std : : vector < Thread > & thread_tab )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2009-06-05 22:29:06 +02:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2009-06-07 04:40:27 +02:00
query < < " select thread.id, thread.parent_id, thread.dir_id, thread.closed, thread.items, thread.last_item, item.date_modification, item.user_id, item.guest_name "
2009-06-05 22:29:06 +02:00
" from core.thread left join core.item on thread.last_item = item.id "
" where thread.parent_id = ' " < < parent_id < < " ' order by date_modification asc; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
2009-04-21 01:49:28 +02:00
2009-06-05 22:29:06 +02:00
int rows = PQntuples ( r ) ;
Thread thread ;
int cid = AssertColumn ( r , " id " ) ;
int cparent_id = AssertColumn ( r , " parent_id " ) ;
int cdir_id = AssertColumn ( r , " dir_id " ) ;
int cclosed = AssertColumn ( r , " closed " ) ;
int citems = AssertColumn ( r , " items " ) ;
int clast_item = AssertColumn ( r , " last_item " ) ;
2010-01-25 05:52:17 +01:00
int cdate_modification = PQfnumber ( r , " date_modification " ) ; // !! czemu tutaj jest pqfnumber zamiast assertcolumn?
2009-06-05 22:29:06 +02:00
int cuser_id = PQfnumber ( r , " user_id " ) ;
2009-06-07 04:40:27 +02:00
int cguest_name = PQfnumber ( r , " guest_name " ) ;
2009-06-05 22:29:06 +02:00
for ( int i = 0 ; i < rows ; + + i )
{
thread . id = atol ( AssertValue ( r , i , cid ) ) ;
thread . parent_id = atol ( AssertValue ( r , i , cparent_id ) ) ;
thread . dir_id = atol ( AssertValue ( r , i , cdir_id ) ) ;
thread . closed = atol ( AssertValue ( r , i , cclosed ) ) = = 0 ? false : true ;
thread . items = atol ( AssertValue ( r , i , citems ) ) ;
thread . last_item . id = atol ( AssertValue ( r , i , clast_item ) ) ;
thread . last_item . date_modification = ConvertTime ( Db : : AssertValue ( r , i , cdate_modification ) ) ;
thread . last_item . user_id = atol ( Db : : AssertValue ( r , i , cuser_id ) ) ;
2009-06-07 04:40:27 +02:00
thread . last_item . guest_name = Db : : AssertValue ( r , i , cguest_name ) ;
2009-06-05 22:29:06 +02:00
thread_tab . push_back ( thread ) ;
}
2009-04-21 01:49:28 +02:00
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
2009-06-05 22:29:06 +02:00
2009-04-21 01:49:28 +02:00
Error Db : : AddThread ( Thread & thread )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2009-04-21 01:49:28 +02:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
2009-06-05 22:29:06 +02:00
query < < " insert into core.thread (parent_id, dir_id, closed, items, last_item) values ( " ;
query < < ' \' ' < < thread . parent_id < < " ', " ;
2009-04-21 01:49:28 +02:00
query < < ' \' ' < < thread . dir_id < < " ', " ;
2009-06-05 22:29:06 +02:00
query < < ' \' ' < < ( thread . closed ? 1 : 0 ) < < " ', " ;
query < < ' \' ' < < thread . items < < " ', " ;
query < < ' \' ' < < thread . last_item . id < < " '); " ;
2009-04-21 01:49:28 +02:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
thread . id = AssertCurrval ( " core.thread_id_seq " ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
2009-06-05 22:29:06 +02:00
Error Db : : EditThreadAddItem ( long dir_id , long item_id )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2009-06-05 22:29:06 +02:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " update core.thread set (last_item, items) = (' " < < item_id < < " ', items+1) where dir_id=' " < < dir_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
2009-06-07 04:40:27 +02:00
Error Db : : EditThreadRemoveItem ( long dir_id )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2009-06-07 04:40:27 +02:00
try
{
AssertConnection ( ) ;
std : : ostringstream query , query2 ;
long last_item_id = - 1 ;
query < < " select id from core.item where parent_id=' " < < dir_id < < " ' order by date_creation desc limit 1; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
if ( PQntuples ( r ) = = 1 )
last_item_id = atol ( AssertValue ( r , 0 , 0 ) ) ;
ClearResult ( r ) ;
query2 < < " update core.thread set (items, last_item) = (items-1,' " < < last_item_id
< < " ') where dir_id=' " < < dir_id < < " '; " ;
r = AssertQuery ( query2 . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
Error Db : : RemoveThread ( long dir_id )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2009-06-07 04:40:27 +02:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " delete from core.thread where dir_id=' " < < dir_id < < " '; " ;
const char * crows = PQcmdTuples ( r ) ;
2010-03-15 18:09:45 +01:00
long rows = 0 ;
2009-06-07 04:40:27 +02:00
if ( crows )
2010-03-15 18:09:45 +01:00
rows = atol ( crows ) ;
if ( rows > 0 )
log < < log2 < < " Db: deleted " < < rows < < " rows from core.thread " < < logend ;
2009-06-07 04:40:27 +02:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
2010-01-25 05:52:17 +01:00
Error Db : : GetTicketByDirId ( long dir_id , Ticket & ticket )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2010-01-25 05:52:17 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select ticket.id, ticket.dir_id, ticket.parent_id, ticket.type, ticket.status, ticket.priority, "
" ticket.category, ticket.expected, ticket.progress, ticket.item_id "
" from core.ticket "
" where ticket.dir_id = ' " < < dir_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
if ( rows > 1 )
log < < log1 < < " Db: there is more than one ticket with dir_id: " < < dir_id < < logend ;
else
if ( rows = = 0 )
2010-02-28 01:08:10 +01:00
throw Error ( WINIX_ERR_NO_TICKET ) ;
2010-01-25 05:52:17 +01:00
TicketColumns tc ;
tc . SetColumns ( r ) ;
tc . SetTicket ( r , 0 , ticket ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
Error Db : : GetTickets ( long parent_id , std : : vector < Ticket > & ticket_tab )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2010-01-25 05:52:17 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select ticket.id, ticket.dir_id, ticket.parent_id, ticket.type, ticket.status, ticket.priority, "
" ticket.category, ticket.expected, ticket.progress, ticket.item_id "
" from core.ticket "
" where ticket.parent_id = ' " < < parent_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
int rows = PQntuples ( r ) ;
Ticket ticket ;
TicketColumns tc ;
tc . SetColumns ( r ) ;
for ( int i = 0 ; i < rows ; + + i )
{
tc . SetTicket ( r , i , ticket ) ;
ticket_tab . push_back ( ticket ) ;
}
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
/*
bool Db : : IsTicket ( long dir_id )
{
PGresult * r = 0 ;
bool is_ticket = false ;
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " select ticket.id from core.ticket "
" where ticket.dir_id = ' " < < dir_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_TUPLES_OK ) ;
is_ticket = ( PQntuples ( r ) = = 1 ) ;
}
catch ( const Error & )
{
}
ClearResult ( r ) ;
return is_ticket ;
}
*/
Error Db : : AddTicket ( Ticket & ticket )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2010-01-25 05:52:17 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " insert into core.ticket (dir_id, parent_id, type, status, priority, category, expected, progress, item_id) values ( " ;
query < < ' \' ' < < ticket . dir_id < < " ', " ;
query < < ' \' ' < < ticket . parent_id < < " ', " ;
query < < ' \' ' < < ticket . type < < " ', " ;
query < < ' \' ' < < ticket . status < < " ', " ;
query < < ' \' ' < < ticket . priority < < " ', " ;
query < < ' \' ' < < ticket . category < < " ', " ;
query < < ' \' ' < < ticket . expected < < " ', " ;
query < < ' \' ' < < ticket . progress < < " ', " ;
query < < ' \' ' < < ticket . item_id < < " '); " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
ticket . id = AssertCurrval ( " core.ticket_id_seq " ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
Error Db : : EditTicketById ( Ticket & ticket )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2010-01-25 05:52:17 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " update core.ticket set (dir_id, parent_id, type, status, priority, category, expected, progress, item_id) = ( " ;
query < < ' \' ' < < ticket . dir_id < < " ', " ;
query < < ' \' ' < < ticket . parent_id < < " ', " ;
query < < ' \' ' < < ticket . type < < " ', " ;
query < < ' \' ' < < ticket . status < < " ', " ;
query < < ' \' ' < < ticket . priority < < " ', " ;
query < < ' \' ' < < ticket . category < < " ', " ;
query < < ' \' ' < < ticket . expected < < " ', " ;
query < < ' \' ' < < ticket . progress < < " ', " ;
query < < ' \' ' < < ticket . item_id < < " ') " ;
query < < " where id=' " < < ticket . id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
2010-02-06 15:08:44 +01:00
Error Db : : EditTicketRemoveItem ( long item_id )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2010-02-06 15:08:44 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " update core.ticket set item_id = '-1' where item_id=' " < < item_id < < " '; " ;
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}
Error Db : : RemoveTicket ( long dir_id )
{
PGresult * r = 0 ;
2010-02-28 01:08:10 +01:00
Error status = WINIX_ERR_OK ;
2010-02-06 15:08:44 +01:00
try
{
AssertConnection ( ) ;
std : : ostringstream query ;
query < < " delete from core.ticket where dir_id=' " < < dir_id < < " '; " ;
const char * crows = PQcmdTuples ( r ) ;
2010-03-15 18:09:45 +01:00
long rows = 0 ;
2010-02-06 15:08:44 +01:00
if ( crows )
2010-03-15 18:09:45 +01:00
rows = atol ( crows ) ;
if ( rows > 0 )
log < < log2 < < " Db: deleted " < < rows < < " rows from core.ticket " < < logend ;
2010-02-06 15:08:44 +01:00
r = AssertQuery ( query . str ( ) ) ;
AssertResultStatus ( r , PGRES_COMMAND_OK ) ;
}
catch ( const Error & e )
{
status = e ;
}
ClearResult ( r ) ;
return status ;
}