winix/winixd/db/db.cpp

1791 lines
37 KiB
C++

/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2008-2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "db.h"
#include "core/log.h"
#include "core/misc.h"
namespace Winix
{
void Db::PostgreSQLsmallerThan10(bool is_smaller_than_10)
{
is_postgresql_smaller_than_10 = is_smaller_than_10;
if( is_postgresql_smaller_than_10 )
{
postgrsql_row_statement.clear();
}
else
{
postgrsql_row_statement = L"ROW";
}
}
bool Db::GetUserPass(const std::wstring & login, long & user_id, UserPass & up)
{
PGresult * r = 0;
bool user_ok = false;
user_id = -1;
try
{
query.Clear();
query << R("select id, has_pass, password, pass_encrypted, pass_type, pass_hash_salted from core.user where login=")
<< login
<< R(";");
r = AssertQuery(query);
AssertResult(r, PGRES_TUPLES_OK);
int rows = Rows(r);
if( rows == 0 )
throw Error(WINIX_ERR_DB_INCORRECT_LOGIN);
if( rows > 1 )
{
log << log1 << "Db: there is more than one user: " << login << logend;
throw Error(WINIX_ERR_DB_MORE_THAN_ONE_LOGIN);
}
int cuser_id = AssertColumn(r, "id");
int chas_pass = AssertColumn(r, "has_pass");
int cpass_type = AssertColumn(r, "pass_type");
int csalted = AssertColumn(r, "pass_hash_salted");
int cpassword = AssertColumn(r, "password");
int cpass_encrypted = AssertColumn(r, "pass_encrypted");
user_ok = true;
user_id = AssertValueLong(r, 0, cuser_id);
up.has_pass = AssertValueBool(r, 0, chas_pass);
up.pass_type = AssertValueInt(r, 0, cpass_type);
up.pass_hash_salted = AssertValueBool(r, 0, csalted);
AssertValueWide(r, 0, cpassword, up.pass);
AssertValueBin(r, 0, cpass_encrypted, up.pass_encrypted);
}
catch(const Error &)
{
}
ClearResult(r);
return user_ok;
}
Error Db::AddUser(User & user, const UserPass & up)
{
PGresult * r = 0;
Error status = WINIX_ERR_OK;
try
{
query.Clear();
query << R("insert into core.user (login, has_pass, password, pass_encrypted, super_user, email,"
"notify, pass_type, pass_hash_salted, env, aenv, status, locale_id, time_zone_id) values (")
<< user.name
<< up.has_pass;
// for safety we put up.pass only if there is not an encrypted version
// someone could have forgotten to clear up.pass
if( up.pass_encrypted.empty() )
query << up.pass;
else
query << "";
query.EPutBin(up.pass_encrypted);
query << user.super_user
<< user.email
<< user.notify
<< up.pass_type
<< up.pass_hash_salted
<< user.env
<< user.aenv
<< user.status
<< user.locale_id
<< user.time_zone_id
<< R(");");
r = AssertQuery(query);
AssertResult(r, PGRES_COMMAND_OK);
user.id = AssertCurrval("core.user_id_seq");
}
catch(const Error & e)
{
status = e;
}
ClearResult(r);
return status;
}
Error Db::ChangeUserPass(long user_id, const UserPass & up)
{
query.Clear();
query << R("update core.user set(has_pass, password, pass_encrypted,"
"pass_type, pass_hash_salted) = ") << R(postgrsql_row_statement) << R("(")
<< up.has_pass;
// for safety
if( up.pass_encrypted.empty() )
query << up.pass;
else
query << "";
query.EPutBin(up.pass_encrypted);
query << up.pass_type
<< up.pass_hash_salted
<< R(") where id=")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserEnv(long user_id, const PT::Space & space)
{
query.Clear();
query << R("update core.user set(env) = ") << R(postgrsql_row_statement) << R("(")
<< space
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserAdminEnv(long user_id, const PT::Space & space)
{
query.Clear();
query << R("update core.user set(aenv) = ") << R(postgrsql_row_statement) << R("(")
<< space
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserStatus(long user_id, int status)
{
query.Clear();
query << R("update core.user set(status) = ") << R(postgrsql_row_statement) << R("(")
<< status
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserEmail(long user_id, const std::wstring & email)
{
query.Clear();
query << R("update core.user set(email) = ") << R(postgrsql_row_statement) << R("(")
<< email
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserLocale(long user_id, size_t locale_id)
{
query.Clear();
query << R("update core.user set(locale_id) = ") << R(postgrsql_row_statement) << R("(")
<< locale_id
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::ChangeUserTimeZone(long user_id, size_t time_zone_id)
{
query.Clear();
query << R("update core.user set(time_zone_id) = ") << R(postgrsql_row_statement) << R("(")
<< time_zone_id
<< R(") where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
Error Db::RemoveUser(long user_id)
{
query.Clear();
query << R("delete from core.user where id = ")
<< user_id
<< R(";");
return DoCommand(query);
}
//!! wywalic z nazwy 'Subject' nic nie jest robione z tytulem
// ta metoda uzywana tez jest w EditParentUrlById()
//bool Db::AddItemCreateUrlSubject(Item & item)
//{
//bool is_that_url;
//PGresult * r = 0;
//int index = 1;
//const int max_index = 99;
//wchar_t appendix[20];
//size_t appendix_len = sizeof(appendix) / sizeof(wchar_t);
//appendix[0] = 0;
//
// // only root dir may not have url
// if( item.parent_id != -1 && item.url.empty() )
// item.url = L"empty";
//
// try
// {
// do
// {
// query_create_url.Clear();
//
// temp_url = item.url;
// temp_url += appendix;
//
// query_create_url
// << R("select id from core.item where url=")
// << temp_url
// << R(" and parent_id=")
// << item.parent_id
// << R(";");
//
// r = AssertQuery(query_create_url);
// AssertResult(r, PGRES_TUPLES_OK);
//
// if( Rows(r) != 0 )
// {
// swprintf(appendix, appendix_len, L"_(%d)", ++index);
// is_that_url = true;
// }
// else
// {
// item.url = temp_url;
// is_that_url = false;
// }
//
// ClearResult(r);
// r = 0;
// }
// while( is_that_url && index <= max_index );
// }
// catch(const Error &)
// {
// is_that_url = true; // for returning false
// }
//
// ClearResult(r);
//
//return !is_that_url;
//}
//Error Db::AddItemIntoItem(Item & item)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
// bool url_without_id = false;
//
// try
// {
// query.Clear();
// query << R("insert into core.item (user_id, modification_user_id, group_id, privileges, "
// "date_creation, date_modification, type, parent_id, content_id, "
// "link_to, link_redirect, subject, guest_name, template, sort_index, meta, ameta, url) values (")
// << item.user_id
// << item.modification_user_id
// << item.group_id
// << item.privileges
// << item.date_creation
// << item.date_modification
// << static_cast<int>(item.type)
// << item.parent_id
// << item.content_id
// << item.link_to
// << item.link_redirect
// << item.subject
// << item.guest_name
// << item.html_template
// << item.sort_index
// << item.meta
// << item.ameta;
//
// url_without_id = AddItemCreateUrlSubject(item);
//
// if( url_without_id )
// query << item.url;
// else
// query << R(", currval('core.item_id_seq')"); // !! zrobic test czy to obecnie dziala dobrze
//
// query << R(");");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
//
// item.id = AssertCurrval("core.item_id_seq");
//
// if( !url_without_id )
// Toa(item.id, item.url);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::AddItemIntoContent(Item & item)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
// int first_ref = 1;
//
// try
// {
// query.Clear();
// query << R("insert into core.content (content, content_type, file_path, file_fs, "
// "file_type, has_thumb, hash, hash_type, file_size, ref, modify_index) values (")
// << item.content
// << static_cast<int>(item.content_type)
// << item.file_path
// << item.file_fs
// << item.file_type
// << static_cast<int>(item.has_thumb)
// << item.hash
// << item.hash_type
// << item.file_size
// << first_ref
// << item.modify_index
// << R(");");
//
// r = AssertQuery(query);
// AssertResult(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)
//{
// BeginTrans();
// Error result = WINIX_ERR_OK;
//
// if( item.type == Item::file )
// result = AddItemIntoContent(item);
// else
// item.content_id = -1;
//
// if( result == WINIX_ERR_OK )
// result = AddItemIntoItem(item);
//
//return EndTrans(result);
//}
//Error Db::IncrementContentRef(long content_id)
//{
// query.Clear();
// query << R("update core.content set (ref) = ") << R(postgrsql_row_statement) << R("(ref + 1) where id = ")
// << content_id
// << R(";");
//
//return DoCommand(query);
//}
//
//
//Error Db::DecrementContentRef(long content_id)
//{
// query.Clear();
// query << R("update core.content set (ref) = ") << R(postgrsql_row_statement) << R("(ref - 1) where id = ")
// << content_id
// << R(";");
//
//return DoCommand(query);
//}
// item.id must be set (it's used by GetContentId)
//Error Db::AddHardLink(Item & item)
//{
// if( item.type != Item::file || item.content_id == -1 )
// return WINIX_ERR_FILE_EXPECTED;
//
// BeginTrans();
// Error result = IncrementContentRef(item.content_id);
//
// if( result == WINIX_ERR_OK )
// result = AddItemIntoItem(item);
//
//return EndTrans(result);
//}
//Error Db::EditItemInItem(Item & item, bool with_url)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
// bool url_without_id = false;
//
// try
// {
// query.Clear();
// query << R("update core.item set (user_id, modification_user_id, group_id, privileges, "
// "date_creation, date_modification, type, link_to, link_redirect, parent_id, subject, "
// "guest_name, template, sort_index, meta, ameta");
//
// if( with_url )
// query << R(", url");
//
// query << R(") = ") << R(postgrsql_row_statement) << R("(")
// << item.user_id
// << item.modification_user_id
// << item.group_id
// << item.privileges
// << item.date_creation
// << item.date_modification
// << static_cast<int>(item.type)
// << item.link_to
// << item.link_redirect
// << item.parent_id
// << item.subject
// << item.guest_name
// << item.html_template
// << item.sort_index
// << item.meta
// << item.ameta;
//
// if( with_url )
// {
// url_without_id = AddItemCreateUrlSubject(item);
//
// if( url_without_id )
// query << item.url;
// else
// query << item.id;
// }
//
// query << R(") where id=") << item.id << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
//
// if( with_url && !url_without_id )
// Toa(item.id, item.url);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::EditItemInContent(Item & item)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// // we don't change 'ref' here
// query.Clear();
// query << R("update core.content set (content, content_type, file_path, file_fs, "
// "file_type, has_thumb, hash, hash_type, file_size, modify_index) = ") << R(postgrsql_row_statement) << R("(")
// << item.content
// << static_cast<int>(item.content_type)
// << item.file_path
// << item.file_fs
// << item.file_type
// << static_cast<int>(item.has_thumb)
// << item.hash
// << item.hash_type
// << item.file_size
// << item.modify_index
// << R(") where id=")
// << item.content_id
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//long Db::GetContentId(long item_id)
//{
// PGresult * r = 0;
// long result = -1;
//
// try
// {
// query.Clear();
// query << R("select content_id from core.item where item.id=")
// << item_id
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// if( Rows(r) == 1 && Cols(r) == 1 )
// result = AssertValueLong(r, 0, 0);
// }
// catch(const Error)
// {
// }
//
// ClearResult(r);
//
//return result;
//}
// item.id must be set
// !! moze nazwa poprostu EditItem (nie trzeba tego ById) ? (sprawdzic czy nie koliduje z inna nazwa)
//Error Db::EditItemById(Item & item, bool with_url)
//{
// BeginTrans();
// Error result = WINIX_ERR_OK;
//
// if( item.type == Item::file )
// {
// item.content_id = GetContentId(item.id);
// result = EditItemInContent(item);
// }
//
// if( result == WINIX_ERR_OK )
// result = EditItemInItem(item, with_url);
//
//return EndTrans(result);
//}
//Error Db::EditItemGetIdsByUrl(Item & item)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// query.Clear();
// query << R("select id, content_id from core.item where parent_id=")
// << item.parent_id
// << R(" and item.url=")
// << item.url
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// if( Rows(r) != 1 )
// throw Error(WINIX_ERR_NO_ITEM);
//
// int cid = AssertColumn(r, "id");
// int cc_id = AssertColumn(r, "content_id");
// item.id = AssertValueLong(r, 0, cid);
// item.content_id = AssertValueLong(r, 0, cc_id);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
// item.url and item.parent_id must be set
//Error Db::EditItemByUrl(Item & item, bool with_url)
//{
// BeginTrans();
// Error result = EditItemGetIdsByUrl(item);
//
// if( result == WINIX_ERR_OK )
// {
// if( item.type == Item::file )
// result = EditItemInContent(item);
//
// if( result == WINIX_ERR_OK )
// result = EditItemInItem(item, with_url);
// }
//
//return EndTrans(result);
//}
//Error Db::EditLinkItem(long id, const std::wstring & link_to, int link_redirect)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// query.Clear();
// query << R("update core.item set (link_to, link_redirect) = ") << R(postgrsql_row_statement) << R("(")
// << link_to
// << link_redirect
// << R(") where id=")
// << id
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
//
// if( AffectedRows(r) == 0 )
// {
// result = WINIX_ERR_NO_ITEM;
// log << log1 << "Db: EditLinkItem: no such an item, id: " << id << logend;
// }
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::EditTemplateItemById(long id, const std::wstring & new_html_template)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// query.Clear();
// query << R("update core.item set (template) = ") << R(postgrsql_row_statement) << R("(")
// << new_html_template
// << R(") where id=")
// << id
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
//
// if( AffectedRows(r) == 0 )
// {
// result = WINIX_ERR_NO_ITEM;
// log << log1 << "Db: EditTemplateItemById: no such an item, id: " << id << logend;
// }
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::EditSortIndexItemById(long id, int sort_index)
//{
// query.Clear();
// query << R("update core.item set (sort_index) = ") << R(postgrsql_row_statement) << R("(")
// << sort_index
// << R(") where id=")
// << id
// << R(";");
//
// return DoCommand(query);
//}
//void Db::GetItemsQuerySelect(const DbItemQuery & iq, DbTextStream & query, bool skip_other_sel)
//{
// query << R("select item.id, content_id");
//
// if( !skip_other_sel )
// {
// if( iq.sel_parent_id ) query << R(", parent_id");
// if( iq.sel_user_id ) query << R(", user_id, modification_user_id");
// if( iq.sel_group_id ) query << R(", group_id");
// if( iq.sel_guest_name) query << R(", guest_name");
// if( iq.sel_privileges ) query << R(", privileges");
// if( iq.sel_date ) query << R(", date_creation, date_modification");
// if( iq.sel_subject ) query << R(", subject");
// if( iq.sel_content ) query << R(", content, content_type, ref, modify_index");
// if( iq.sel_url ) query << R(", url");
// if( iq.sel_type ) query << R(", type");
// if( iq.sel_link ) query << R(", link_to, link_redirect");
// if( iq.sel_file ) query << R(", file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size");
// if( iq.sel_html_template ) query << R(", template");
// if( iq.sel_sort_index ) query << R(", sort_index");
// if( iq.sel_meta ) query << R(", meta, ameta");
// }
//
// query << R(" from core.item");
//}
//void Db::GetItemsQueryJoin(const DbItemQuery & iq, DbTextStream & query)
//{
// if( iq.sel_content || iq.sel_file || iq.where_file_type )
// query << R(" left join core.content on item.content_id = content.id");
//}
//void Db::GetItemsQueryWhere(const DbItemQuery & iq, DbTextStream & query)
//{
// if( iq.where_id || iq.where_parent_id || iq.where_type || iq.where_file_type )
// {
// query << R(" where ");
// const char * add_and = " and ";
// const char * if_and = "";
//
// if( iq.where_id ) { query << R(if_and) << R("item.id=") << iq.id ; if_and = add_and; }
//
// if( iq.id_tab && !iq.id_tab->empty() )
// {
// CreateIdList(*iq.id_tab, iq_id_list);
// query << R(if_and) << R("item.id in ") << R(iq_id_list);
// if_and = add_and;
// }
//
// if( iq.where_parent_id ){ query << R(if_and) << R("parent_id=") << iq.parent_id ; if_and = add_and; }
//
// if( iq.where_type )
// {
// query << R(if_and) << R("type");
//
// if( iq.type_equal )
// query << R("=");
// else
// query << R("!=");
//
// query << int(iq.type);
// if_and = add_and;
// }
//
//
// if( iq.where_file_type )
// {
// query << R(if_and) << R("file_type");
//
// if( iq.file_type_equal )
// query << R("=");
// else
// query << R("!=");
//
// query << iq.file_type;
// if_and = add_and;
// }
// }
//}
//void Db::GetItemsQueryOrder(bool sort_asc)
//{
// if( sort_asc )
// query << R(" asc");
// else
// query << R(" desc");
//}
//void Db::GetItemsQueryOrder(const DbItemQuery & iq, DbTextStream & query)
//{
// if( iq.sel_sort_index || iq.sel_date )
// {
// query << R(" order by");
//
// if( iq.sel_sort_index )
// {
// query << R(" sort_index");
// GetItemsQueryOrder(iq.sort_index_asc);
// }
//
// if( iq.sel_date )
// {
// if( iq.sel_sort_index )
// query << R(",");
//
// query << R(" item.date_creation");
// GetItemsQueryOrder(iq.sort_date_asc);
// }
// }
//}
//void Db::GetItemsQueryLimit(const DbItemQuery & iq, DbTextStream & query)
//{
// if( iq.limit != 0 )
// query << R(" limit ") << iq.limit;
//
// if( iq.offset != 0 )
// query << R(" offset ") << iq.offset;
//}
//PGresult * Db::GetItemsQuery(const DbItemQuery & iq, DbTextStream & query, bool skip_other_sel)
//{
// query.Clear();
//
// GetItemsQuerySelect(iq, query, skip_other_sel);
// GetItemsQueryJoin(iq, query);
// GetItemsQueryWhere(iq, query);
// GetItemsQueryOrder(iq, query);
// GetItemsQueryLimit(iq, query);
//
// query << R(";");
//
//return AssertQuery(query);
//}
//PGresult * Db::GetItemsQuery(const DbItemQuery & iq, bool skip_other_sel)
//{
// return GetItemsQuery(iq, query, skip_other_sel);
//}
//void Db::GetItems(std::vector<Item> & item_tab, const DbItemQuery & item_query)
//{
// item_tab.clear();
// PGresult * r = 0;
//
// try
// {
// r = GetItemsQuery(item_query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// get_item_temp.Clear();
// int rows = Rows(r);
//
// if( rows > 0 && size_t(rows) > item_tab.capacity() )
// item_tab.reserve(rows);
//
// item_cols.SetColumns(r);
//
// for(int i=0 ; i<rows ; ++i)
// {
// item_tab.push_back(get_item_temp);
// item_cols.SetItem(r, i, item_tab.back());
// }
// }
// catch(const Error &)
// {
// }
//
// ClearResult(r);
//}
//void Db::GetItems(std::vector<long> & item_tab, const DbItemQuery & item_query)
//{
// item_tab.clear();
// PGresult * r = 0;
//
// try
// {
// r = GetItemsQuery(item_query, true);
// AssertResult(r, PGRES_TUPLES_OK);
//
// int rows = Rows(r);
//
// for(int i = 0 ; i<rows ; ++i)
// {
// long id = AssertValueLong(r, i, 0);
// item_tab.push_back(id);
// }
// }
// catch(const Error &)
// {
// }
//
// ClearResult(r);
//}
//Error Db::GetItem(Item & item, const DbItemQuery & item_query)
//{
// item.Clear();
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// r = GetItemsQuery(item_query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// int rows = Rows(r);
//
// if( rows == 1 )
// {
// item_cols.SetColumns(r);
// item_cols.SetItem(r, 0, item);
// }
// else
// if( rows == 0 )
// {
// result = WINIX_ERR_NO_ITEM;
// }
// else
// {
// result = WINIX_ERR_NO_ITEM;
// log << log1 << "Db: more than one item matches the query (" << rows << ")";
// }
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
// how many items there are in a 'parent_id' directory
//long Db::Size(long parent_id, Item::Type type)
//{
// PGresult * r = 0;
// long res = 0;
//
// try
// {
// query.Clear();
// query << R("select count(id) from core.item where ");
//
// if( type != Item::none )
// query << R("type=") << (int)type << R(" and ");
//
// query << R("parent_id=") << parent_id << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// res = AssertValueLong(r, 0, 0);
// }
// catch(const Error &)
// {
// }
//
// ClearResult(r);
//
//return res;
//}
// !! nowy interfejs
//Error Db::GetItem(long parent_id, const std::wstring & url, Item & item)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// query.Clear();
// query << R("select * from core.item left join core.content on item.content_id = content.id"
// " where item.parent_id=")
// << parent_id
// << R(" and item.url=")
// << url
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// if( Rows(r) == 0 )
// throw Error(WINIX_ERR_NO_ITEM);
//
// item_cols.SetColumns(r);
// item_cols.SetItem(r, 0, item);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::GetItemById(long item_id, Item & item)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// query.Clear();
// query << R("select * from core.item left join core.content on item.content_id = content.id"
// " where item.id=") << item_id << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// if( Rows(r) == 0 )
// throw Error(WINIX_ERR_NO_ITEM);
//
// item_cols.SetColumns(r);
// item_cols.SetItem(r, 0, item);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//
//return result;
//}
//long Db::GetItemId(long parent_id, const std::wstring & url, Item::Type type)
//{
// PGresult * r = 0;
// long result = -1;
//
// try
// {
// query.Clear();
// query << R("select id from core.item where type=")
// << static_cast<int>(type)
// << R(" and item.parent_id=")
// << parent_id
// << R(" and item.url=")
// << url
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// if( Rows(r) == 1 )
// result = AssertValueLong(r, 0, 0);
// }
// catch(const Error & e)
// {
// }
//
// ClearResult(r);
//
//return result;
//}
//long Db::GetFileId(long parent_id, const std::wstring & url)
//{
// return GetItemId(parent_id, url, Item::file);
//}
//long Db::GetDirId(long parent_id, const std::wstring & url)
//{
// return GetItemId(parent_id, url, Item::dir);
//}
//bool Db::GetPriv(Item & item, long id)
//{
//bool result = false;
//
// PGresult * r = 0;
//
// try
// {
// query.Clear();
// query << R("select user_id, modification_user_id, group_id, privileges, guest_name from core.item"
// " where item.id=")
// << id
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// if( Rows(r) != 1 )
// throw Error();
//
// item_cols.SetColumns(r);
// item_cols.SetItem(r, 0, item);
//
// result = true;
// }
// catch(const Error &)
// {
// }
//
// ClearResult(r);
//
//return result;
//}
// !! to jest nowy interfejs, z jawnym podaniem id
//Error Db::EditPrivById(Item & item, long id)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// query.Clear();
// query << R("update core.item set (user_id, modification_user_id, group_id, privileges, guest_name) = ") << R(postgrsql_row_statement) << R("(")
// << item.user_id
// << item.modification_user_id
// << item.group_id
// << item.privileges
// << item.guest_name
// << R(") where id=")
// << id
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::EditParentUrlById(Item & item, long id)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
// bool url_without_id = false;
//
// try
// {
// query.Clear();
// query << R("update core.item set (parent_id, url) = ") << R(postgrsql_row_statement) << R("(") << item.parent_id;
//
// url_without_id = AddItemCreateUrlSubject(item);
//
// if( url_without_id )
// query << item.url;
// else
// query << item.id;
//
// query << R(") where id=") << id << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::EditFileById(const Item & item, long id)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// BeginTrans();
//
// try
// {
// long content_id = GetContentId(id);
//
// if( content_id == -1 )
// throw Error(WINIX_ERR_NO_ITEM);
//
// query.Clear();
// query << R("update core.content set (file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size) = ") << R(postgrsql_row_statement) << R("(")
// << item.file_path
// << item.file_fs
// << item.file_type
// << static_cast<int>(item.has_thumb)
// << item.hash
// << item.hash_type
// << item.file_size
// << R(") where id=") << content_id << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return EndTrans(result);
//}
//Error Db::EditHasThumbById(bool has_thumb, long id)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// BeginTrans();
//
// try
// {
// long content_id = GetContentId(id);
//
// if( content_id == -1 )
// throw Error(WINIX_ERR_NO_ITEM);
//
// query.Clear();
// query << R("update core.content set (has_thumb) = ") << R(postgrsql_row_statement) << R("(")
// << static_cast<int>(has_thumb)
// << R(") where id=") << content_id << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return EndTrans(result);
//}
//Error Db::EditMetaById(const PT::Space & meta, long id)
//{
// query.Clear();
// query << R("update core.item set (meta) = ") << R(postgrsql_row_statement) << R("(")
// << meta
// << R(") where id=")
// << id
// << R(";");
//
//return DoCommand(query);
//}
//Error Db::EditAdminMetaById(const PT::Space & ameta, long id)
//{
// query.Clear();
// query << R("update core.item set (ameta) = ") << R(postgrsql_row_statement) << R("(")
// << ameta
// << R(") where id=")
// << id
// << R(";");
//
//return DoCommand(query);
//}
//Error Db::EditSubjectById(Item & item, long id)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// query.Clear();
// query << R("update core.item set (subject) = ") << R(postgrsql_row_statement) << R("(")
// << item.subject
// << R(") where id=")
// << id
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::DelDirById(long id)
//{
// Error result = WINIX_ERR_OK;
// PGresult * r = 0;
//
// BeginTrans();
//
// try
// {
// // decrementing ref in core.content
// query.Clear();
// query << R("update core.content set (ref) = ") << R(postgrsql_row_statement) << R("(ref - 1) where content.id in "
// "(select content_id from core.item where type=1 and parent_id=")
// << id
// << R(");");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
// ClearResult(r);
//
// // deleting in core.content where ref is zero
// query.Clear();
// query << R("delete from core.content where ref=0;");
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
// log << log2 << "Db: deleted " << AffectedRows(r) << " rows from core.content" << logend;
// ClearResult(r);
//
// // deleting from core.item
// query.Clear();
// query << R("delete from core.item where id=")
// << id
// << R(" or parent_id=")
// << id
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
// log << log2 << "Db: deleted dir: " << id << " (deleted: " << AffectedRows(r) << " rows from core.item)" << logend;
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return EndTrans(result);
//}
//Error Db::DelItemDelItem(long item_id, int type)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// query.Clear();
// query << R("delete from core.item where id=")
// << item_id
// << R(" and type=")
// << type
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
//
// log << log2 << "Db: deleted " << AffectedRows(r) << " from core.item" << logend;
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::DelItemDelContent(long content_id)
//{
// PGresult * r = 0;
// Error result = WINIX_ERR_OK;
//
// try
// {
// result = DecrementContentRef(content_id);
//
// if( result == WINIX_ERR_OK )
// {
// query.Clear();
// query << R("delete from core.content where ref=0 and id=")
// << content_id
// << R(";");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_COMMAND_OK);
//
// log << log2 << "Db: deleted " << AffectedRows(r) << " rows from core.content" << logend;
// }
// }
// catch(const Error & e)
// {
// result = e;
// }
//
// ClearResult(r);
//
//return result;
//}
//Error Db::DelItem(const Item & item)
//{
//Error result = WINIX_ERR_NO_ITEM;
//
// if( item.type == Item::file )
// {
// BeginTrans();
// result = DelItemDelContent(item.content_id);
//
// if( result == WINIX_ERR_OK )
// result = DelItemDelItem(item.id, 1);
//
// result = EndTrans(result);
// }
// else
// if( item.type == Item::symlink )
// {
// result = DelItemDelItem(item.id, 2);
// }
// else
// if( item.type == Item::dir )
// {
// result = DelDirById(item.id);
// }
//
//return result;
//}
//Error Db::DelFileById(long file_id)
//{
//Error result = WINIX_ERR_NO_ITEM;
//
// BeginTrans();
//
// long content_id = GetContentId(file_id);
//
// if( content_id != -1 )
// {
// result = DelItemDelContent(content_id);
//
// if( result == WINIX_ERR_OK )
// result = DelItemDelItem(file_id, 1);
// }
//
// result = EndTrans(result);
//
//return result;
//}
//Error Db::DelSymlinkById(long symlink_id)
//{
// return DelItemDelItem(symlink_id, 2);
//}
//void Db::GetDirs(DirContainer & dir_tab)
//{
// PGresult * r = 0;
//
// try
// {
// query.Clear();
// query << R("select * from core.item where type=0;");
//
// r = AssertQuery(query);
// AssertResult(r, PGRES_TUPLES_OK);
//
// dir_temp.Clear();
// int rows = Rows(r);
// item_cols.SetColumns(r);
//
// for(int i=0 ; i<rows ; ++i)
// {
// item_cols.SetItem(r, i, dir_temp);
// dir_tab.PushBack(dir_temp);
// }
// }
// catch(const Error &)
// {
// }
//
// ClearResult(r);
//}
void Db::GetUsers(UGContainer<User> & user_tab)
{
PGresult * r = 0;
try
{
query.Clear();
query << R("select id, login, super_user, group_id, email, notify,"
" env, aenv, status, locale_id, time_zone_id"
" from core.user left outer join core.group_mem on"
" core.user.id = core.group_mem.user_id order by id asc;");
r = AssertQuery(query);
AssertResult(r, PGRES_TUPLES_OK);
int rows = Rows(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");
int cemail = AssertColumn(r, "email");
int cnotify = AssertColumn(r, "notify");
int cenv = AssertColumn(r, "env");
int caenv = AssertColumn(r, "aenv");
int cstatus = AssertColumn(r, "status");
int clocale_id = AssertColumn(r, "locale_id");
int ctzone_id = AssertColumn(r, "time_zone_id");
User u;
long last_id = -1;
UGContainer<User>::Iterator iter = user_tab.End();
for(int i=0 ; i<rows ; ++i)
{
u.id = AssertValueLong(r, i, cid);
if( u.id != last_id )
{
u.name = AssertValueWide(r, i, cname);
u.super_user = AssertValueBool(r, i, csuper_user);
u.email = AssertValueWide(r, i, cemail);
u.notify = AssertValueInt(r, i, cnotify);
u.status = AssertValueInt(r, i, cstatus);
u.locale_id = (size_t)AssertValueInt(r, i, clocale_id);
u.time_zone_id = (size_t)AssertValueInt(r, i, ctzone_id);
AssertValueSpace(r, i, cenv, u.env);
AssertValueSpace(r, i, caenv, u.aenv);
log << log2 << "Db: user: id: " << u.id << ", name: " << u.name << ", super_user: " << u.super_user << logend;
iter = user_tab.PushBack(u);
if( iter == user_tab.End() )
log << log1 << "Db: can't add a user: " << u.name << logend;
last_id = u.id;
}
long group_id = AssertValueLong(r, i, cgroup_id);
if( !IsNull(r, i, cgroup_id) && group_id!=-1 && iter!=user_tab.End() )
{
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);
}
void Db::GetGroups(UGContainer<Group> & group_tab)
{
PGresult * r = 0;
try
{
query.Clear();
query << R("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);
AssertResult(r, PGRES_TUPLES_OK);
int rows = Rows(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 = AssertValueLong(r, i, cid);
if( g.id != last_id )
{
g.name = AssertValueWide(r, i, cname);
log << log3 << "Db: get group, id: " << g.id << ", group: " << g.name << logend;
iter = group_tab.PushBack( g );
last_id = g.id;
}
long user_id = AssertValueLong(r, i, cuser_id);
if( !IsNull(r, i, cuser_id) && user_id!=-1 && !group_tab.Empty() )
{
iter->members.push_back(user_id);
log << log3 << "Db: get group member: user_id: " << user_id << logend;
}
}
}
catch(const Error &)
{
}
ClearResult(r);
}
} // namespace Winix