/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2010-2014, 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 "tdb.h" #include "core/log.h" namespace Winix { namespace Thread { Error TDb::AddThread(const Thread & thread) { query.Clear(); query << R("insert into plugins.thread (file_id, replies, last_item, closed) values (") << thread.file_id << thread.replies << thread.last_item_id << (thread.closed ? 1 : 0 ) << R(");"); return DoCommand(query); } void TDb::SetThreadColumns(PGresult * r) { cfile_id = AssertColumn(r, "file_id"); creplies = AssertColumn(r, "replies"); cclosed = AssertColumn(r, "closed"); clast_item = AssertColumn(r, "last_item"); cdate_modification = AssertColumn(r, "date_modification"); cuser_id = AssertColumn(r, "user_id"); cguest = AssertColumn(r, "guest_name"); } void TDb::SetThread(PGresult * r, int col, Thread & thread) { thread.file_id = AssertValueLong(r, col, cfile_id); thread.replies = AssertValueLong(r, col, creplies); thread.closed = AssertValueBool(r, col, cclosed); thread.last_item_id = AssertValueLong(r, col, clast_item); thread.last_item_date_modification = AssertValueDate(r, col, cdate_modification); thread.last_item_user_id = AssertValueLong(r, col, cuser_id); AssertValueWide(r, col, cguest, thread.last_item_guest_name); } Error TDb::GetThread(long file_id, Thread & thread) { PGresult * r = 0; Error status = WINIX_ERR_OK; try { query.Clear(); query << R("select thread.file_id, thread.replies, thread.closed, thread.last_item, " "item.date_modification, item.user_id, item.guest_name " "from plugins.thread left join core.item on thread.last_item = item.id " "where thread.file_id = ") << file_id << R(";"); r = AssertQuery(query); AssertResult(r, PGRES_TUPLES_OK); int rows = Rows(r); if( rows > 1 ) log << log1 << "ThreadDb: there is more than one thread with file_id: " << file_id << logend; else if( rows == 0 ) throw Error(WINIX_ERR_NO_THREAD); SetThreadColumns(r); SetThread(r, 0, thread); } catch(const Error & e) { status = e; } ClearResult(r); return status; } Error TDb::GetThreads(const std::vector & file_id_tab, std::vector & thread_tab) { PGresult * r = 0; Error status = WINIX_ERR_OK; thread_tab.clear(); if( file_id_tab.empty() ) return status; try { CreateIdList(file_id_tab, list_id); // they should be sorted by file_id (they are used in a binary search later) query.Clear(); query << R("select thread.file_id, thread.replies, thread.closed, thread.last_item, " "item.date_modification, item.user_id, item.guest_name " "from plugins.thread left join core.item on thread.last_item = item.id " "where thread.file_id in ") << R(list_id) << R(" order by file_id asc;"); r = AssertQuery(query); AssertResult(r, PGRES_TUPLES_OK); int rows = Rows(r); SetThreadColumns(r); for(int i=0 ; i & answer_id_tab) { PGresult * r = 0; Error status = WINIX_ERR_OK; answer_id_tab.clear(); try { query.Clear(); query << R("select answer_id from plugins.thread_files " "where file_id = ") << file_id << R(";"); r = AssertQuery(query); AssertResult(r, PGRES_TUPLES_OK); int rows = Rows(r); answer_id_tab.resize(rows); for(int i=0 ; i 0 ) log << log2 << "ThreadDb: deleted " << rows << " rows from plugins.thread_files" << logend; // setting new last_items to the files status = RemoveAnswerRecalcLast(file_id_tab); } catch(const Error & e) { status = e; } ClearResult(r1); ClearResult(r2); return status; } Error TDb::RemoveAnswerRecalcLast(long file_id) { long last_item_id = FindLastAnswer(file_id); query.Clear(); query << R("update plugins.thread set (replies, last_item) = (replies-1,") << last_item_id << R(") where file_id=") << file_id << R(";"); return DoCommand(query); } Error TDb::RemoveAnswerRecalcLast(const std::vector & file_id_tab) { for(size_t i=0 ; i 0 ) log << log2 << "ThreadDb: deleted " << rows << " rows from plugins.thread" << logend; ClearResult(r); query.Clear(); query << R("delete from plugins.thread_files where file_id=") << file_id << R(";"); r = AssertQuery(query); AssertResult(r, PGRES_COMMAND_OK); rows = AffectedRows(r); if( rows > 0 ) log << log2 << "ThreadDb: deleted " << rows << " rows from plugins.thread_files" << logend; } catch(const Error & e) { status = e; } ClearResult(r); return status; } Error TDb::RemoveAnswerOnly(long answer_id) { PGresult * r = 0; Error status = WINIX_ERR_OK; try { query.Clear(); query << R("delete from plugins.thread_files where answer_id=") << answer_id << R(";"); r = AssertQuery(query); AssertResult(r, PGRES_COMMAND_OK); long rows = AffectedRows(r); if( rows > 0 ) log << log2 << "ThreadDb: deleted " << rows << " rows from plugins.thread_files" << logend; } catch(const Error & e) { status = e; } ClearResult(r); return status; } void TDb::GetAllThreadsId(std::vector & file_id) { PGresult * r = 0; file_id.clear(); try { query.Clear(); query << R("select file_id from plugins.thread;"); r = AssertQuery(query); AssertResult(r, PGRES_TUPLES_OK); int rows = Rows(r); file_id.resize(rows); for(int i=0 ; i