Sorted Socket.
[UnsignedByte.git] / src / DAL / SqliteMgr.cpp
bloba834a8b3132a2197c4f7509e49891da741bb432d
1 /***************************************************************************
2 * Copyright (C) 2008 by Sverre Rabbelier *
3 * sverre@rabbelier.nl *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "SavableManager.h"
22 #include "SavableManagers.h"
23 #include "SelectionMask.h"
24 #include "TableImpl.h"
25 #include "FieldImpl.h"
26 #include "KeyImpl.h"
27 #include "KeyValue.h"
28 #include "Join.h"
29 #include "SqliteMgr.h"
30 #include "DatabaseMgr.h"
31 #include "Statements.h"
32 #include "StatementStrings.h"
33 #include "Assert.h"
34 #include "Global.h"
36 extern bool g_printsql;
38 SqliteMgr::SqliteMgr()
40 m_db = DatabaseMgr::Get()->DB();
41 m_odb = m_db->grabdb();
43 Assert(m_db);
44 Assert(m_odb);
47 SqliteMgr::~SqliteMgr()
49 m_db->freedb(m_odb);
52 void SqliteMgr::doInsert(SavableManager* bindable)
54 Assert(bindable);
56 TableImpl* table = bindable->getTable().get();
57 Assert(table);
59 sqlite3_stmt* insert = getInsertStmt(table);
60 Assert(insert);
62 sqlite3_reset(insert);
64 if(table->primarykeysize() > 1)
65 bindable->bindKeys(m_odb->db, insert);
67 doStatement(insert);
69 if(table->primarykeysize() == 1)
70 bindable->parseInsert(m_odb->db);
72 commit(table);
75 void SqliteMgr::doErase(SavableManager* bindable)
77 Assert(bindable);
79 TableImpl* table = bindable->getTable().get();
80 Assert(table);
82 sqlite3_stmt* erase = getEraseStmt(table);
83 Assert(erase);
85 sqlite3_reset(erase);
87 bindable->bindKeys(m_odb->db, erase);
88 doStatement(erase);
90 commit(table);
93 void SqliteMgr::doUpdate(SavableManager* bindable)
95 Assert(bindable);
97 TableImpl* table = bindable->getTable().get();
98 Assert(table);
100 // This table doesn't have any properties, it need not be updated.
101 if(table->size() <= table->primarykeysize())
102 return;
104 sqlite3_stmt* update = getUpdateStmt(table);
105 Assert(update);
107 sqlite3_reset(update);
109 bindable->bindUpdate(m_odb->db, update);
110 doStatement(update);
112 commit(table);
115 void SqliteMgr::doSelect(SavableManager* bindable)
117 Assert(bindable);
119 TableImpl* table = bindable->getTable().get();
120 Assert(table);
122 sqlite3_stmt* select = getSelectStmt(table);
123 Assert(select);
125 sqlite3_reset(select);
127 bindable->bindKeys(m_odb->db, select);
128 bool row = doStatement(select);
129 if(row)
130 bindable->parseSelect(select);
131 else
132 throw RowNotFoundException("SqliteMgr::doSelect(), no row.");
135 void SqliteMgr::doLookup(SavableManager* bindable, FieldPtr field)
137 Assert(bindable);
138 Assert(field);
140 TableImpl* table = bindable->getTable().get();
141 Assert(table);
143 sqlite3_stmt* lookup = getLookupStmt(table, field);
144 Assert(lookup);
146 sqlite3_reset(lookup);
148 bindable->bindLookup(m_odb->db, lookup);
149 bool row = doStatement(lookup);
150 if(row)
152 bindable->parseLookup(lookup);
153 doSelect(bindable);
155 else
156 throw RowNotFoundException("SqliteMgr::doLookup(), no row.");
159 void SqliteMgr::doSelectMulti(SelectionMask* mask)
161 Assert(mask);
163 sqlite3_stmt* selectMulti = getSelectMultiStmt(mask, false);
164 Assert(selectMulti);
166 sqlite3_reset(selectMulti);
168 mask->bindSelectMulti(m_odb->db, selectMulti);
170 bool good = true;
171 for(int i = 0; good; i++)
173 good = doStatement(selectMulti);
174 if(good)
175 mask->parseRow(selectMulti);
178 sqlite3_finalize(selectMulti);
181 void SqliteMgr::doCount(SelectionMask* mask)
183 Assert(mask);
185 sqlite3_stmt* count = getSelectMultiStmt(mask, true);
186 Assert(count);
188 sqlite3_reset(count);
190 mask->bindSelectMulti(m_odb->db, count);
192 bool good = doStatement(count);
194 if(good)
195 mask->parseCount(count);
197 sqlite3_finalize(count);
200 void SqliteMgr::commit(TableImpl* table)
202 Assert(table);
203 m_statements.clear();
206 bool SqliteMgr::doStatement(sqlite3_stmt* stmt)
208 Assert(stmt);
210 int rc = sqlite3_step(stmt);
212 switch(rc) {
213 case SQLITE_DONE:
214 return false;
215 case SQLITE_ROW:
216 return true;
219 throw SqliteError(m_odb->db);
222 StatementsPtr SqliteMgr::getStatements(TableImpl* table)
224 Assert(table);
226 StatementsPtr statements = m_statements[table];
227 if(statements)
228 return statements;
230 statements = StatementsPtr(new Statements());
232 m_statements[table] = statements;
233 return statements;
236 StatementStringsPtr SqliteMgr::getStatementStrings(TableImpl* table)
238 Assert(table);
240 StatementStringsPtr statements = m_statementstrings[table];
241 if(statements)
242 return statements;
244 statements = StatementStringsPtr(new StatementStrings());
246 m_statementstrings[table] = statements;
247 return statements;
250 sqlite3_stmt* SqliteMgr::getInsertStmt(TableImpl* table)
252 Assert(table);
254 StatementsPtr statements = getStatements(table);
255 sqlite3_stmt* statement = statements->getInsert();
256 if(statement)
257 return statement;
259 std::string sql;
261 StatementStringsPtr statementstrings = getStatementStrings(table);
262 cstring statementstring = statementstrings->getInsert();
264 if(statementstring.size() != 0)
266 sql = statementstring;
268 else
270 sql.append("INSERT INTO ");
271 sql.append(table->getName());
272 sql.append(" (");
273 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
275 FieldImplPtr field = *it;
276 Assert(field);
278 if(!field->isPrimaryKey())
279 continue;
281 if(it != table->begin())
282 sql.append(", ");
284 sql.append(field->getName());
286 sql.append(") VALUES(");
287 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
289 FieldImplPtr field = *it;
290 Assert(field);
292 if(!field->isPrimaryKey())
293 continue;
295 if(it != table->begin())
296 sql.append(", ");
298 if(table->primarykeysize() == 1)
299 sql.append("NULL");
300 else
301 sql.append("?");
303 sql.append(");");
305 statementstrings->setInsert(sql);
308 if(g_printsql) {
309 Global::Get()->printsql(sql);
312 int errorcode = sqlite3_prepare_v2(m_odb->db, sql.c_str(), (int)sql.size(), &statement, &m_leftover);
314 if(errorcode != SQLITE_OK)
315 throw SqliteError(m_odb->db, sql);
317 Assert(m_leftover == NULL || strlen(m_leftover) == 0);
319 statements->setInsert(statement);
320 return statement;
323 sqlite3_stmt* SqliteMgr::getEraseStmt(TableImpl* table)
325 StatementsPtr statements = getStatements(table);
326 sqlite3_stmt* statement = statements->getErase();
327 if(statement)
328 return statement;
330 std::string sql;
332 StatementStringsPtr statementstrings = getStatementStrings(table);
333 cstring statementstring = statementstrings->getErase();
335 if(statementstring.size() != 0)
337 sql = statementstring;
339 else
341 sql.append("DELETE FROM ");
342 sql.append(table->getName());
343 sql.append(" WHERE ");
344 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
346 FieldImplPtr field = *it;
347 Assert(field);
349 if(!field->isPrimaryKey())
350 continue;
352 if(it != table->begin())
353 sql.append(", ");
355 sql.append(field->getName());
356 sql.append("=?");
358 sql.append(";");
360 statementstrings->setErase(sql);
363 if(g_printsql) {
364 Global::Get()->printsql(sql);
367 int errorcode = sqlite3_prepare_v2(m_odb->db, sql.c_str(), (int)sql.size(), &statement, &m_leftover);
369 if(errorcode != SQLITE_OK)
370 throw SqliteError(m_odb->db, sql);
372 Assert(m_leftover == NULL || strlen(m_leftover) == 0);
374 statements->setErase(statement);
375 return statement;
378 sqlite3_stmt* SqliteMgr::getUpdateStmt(TableImpl* table)
380 StatementsPtr statements = getStatements(table);
381 sqlite3_stmt* statement = statements->getUpdate();
382 if(statement)
383 return statement;
385 std::string sql;
387 StatementStringsPtr statementstrings = getStatementStrings(table);
388 cstring statementstring = statementstrings->getUpdate();
390 if(statementstring.size() != 0)
392 sql = statementstring;
394 else
396 sql.append("UPDATE ");
397 sql.append(table->getName());
398 sql.append(" SET ");
400 bool comspace = false;
401 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
403 FieldImplPtr field = *it;
404 Assert(field);
406 if(field->isPrimaryKey())
407 continue;
409 if(comspace)
410 sql.append(", ");
412 sql.append(field->getName());
413 sql.append("=?");
415 comspace = true;
417 sql.append(" WHERE ");
418 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
420 FieldImplPtr field = *it;
421 Assert(field);
423 if(!field->isPrimaryKey())
424 continue;
426 if(it != table->begin())
427 sql.append(" AND ");
429 sql.append(field->getName());
430 sql.append("=?");
432 sql.append(";");
434 statementstrings->setUpdate(sql);
437 if(g_printsql) {
438 Global::Get()->printsql(sql);
441 int errorcode = sqlite3_prepare_v2(m_odb->db, sql.c_str(), (int)sql.size(), &statement, &m_leftover);
443 if(errorcode != SQLITE_OK)
444 throw SqliteError(m_odb->db, sql);
446 Assert(m_leftover == NULL || strlen(m_leftover) == 0);
448 statements->setUpdate(statement);
449 return statement;
452 sqlite3_stmt* SqliteMgr::getSelectStmt(TableImpl* table)
454 StatementsPtr statements = getStatements(table);
455 sqlite3_stmt* statement = statements->getSelect();
456 if(statement)
457 return statement;
459 std::string sql;
461 StatementStringsPtr statementstrings = getStatementStrings(table);
462 cstring statementstring = statementstrings->getSelect();
464 if(statementstring.size() != 0)
466 sql = statementstring;
468 else
470 sql.append("SELECT ");
472 bool comspace = false;
473 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
475 FieldImplPtr field = *it;
476 Assert(field);
478 if(field->isPrimaryKey())
479 continue;
481 if(comspace)
482 sql.append(", ");
484 sql.append(field->getName());
485 comspace = true;
489 * Prevent queries in the form "SELECT FROM ....", this is for tables that consist of only primary keys.
491 if(table->primarykeysize() == table->size())
492 sql.append("*");
494 sql.append(" FROM ");
495 sql.append(table->getName());
496 sql.append(" WHERE ");
498 bool andspace = false;
499 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
501 FieldImplPtr field = *it;
502 Assert(field);
504 if(!field->isPrimaryKey())
505 continue;
507 if(andspace)
508 sql.append(" AND ");
510 sql.append(field->getName());
511 sql.append("=?");
512 andspace = true;
514 sql.append(";");
516 statementstrings->setSelect(sql);
519 if(g_printsql) {
520 Global::Get()->printsql(sql);
523 int errorcode = sqlite3_prepare_v2(m_odb->db, sql.c_str(), (int)sql.size(), &statement, &m_leftover);
525 if(errorcode != SQLITE_OK)
526 throw SqliteError(m_odb->db, sql);
528 Assert(m_leftover == NULL || strlen(m_leftover) == 0);
530 statements->setSelect(statement);
531 return statement;
534 sqlite3_stmt* SqliteMgr::getLookupStmt(TableImpl* table, FieldPtr lookupfield)
536 StatementsPtr statements = getStatements(table);
537 sqlite3_stmt* statement = statements->getLookup(lookupfield);
538 if(statement)
539 return statement;
541 std::string sql;
543 StatementStringsPtr statementstrings = getStatementStrings(table);
544 cstring statementstring = statementstrings->getLookup(lookupfield);
546 if(statementstring.size() != 0)
548 sql = statementstring;
550 else
552 sql.append("SELECT ");
553 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
555 FieldImplPtr field = *it;
556 Assert(field);
558 if(it != table->begin())
559 sql.append(", ");
561 sql.append(field->getName());
563 sql.append(" FROM ");
564 sql.append(table->getName());
565 sql.append(" WHERE ");
566 sql.append(lookupfield->getName());
567 sql.append("=?");
568 sql.append(";");
570 statementstrings->setLookup(lookupfield, sql);
573 if(g_printsql) {
574 Global::Get()->printsql(sql);
577 int errorcode = sqlite3_prepare_v2(m_odb->db, sql.c_str(), (int)sql.size(), &statement, &m_leftover);
579 if(errorcode != SQLITE_OK)
580 throw SqliteError(m_odb->db, sql);
582 Assert(m_leftover == NULL || strlen(m_leftover) == 0);
584 statements->setLookup(lookupfield, statement);
585 return statement;
588 sqlite3_stmt* SqliteMgr::getSelectMultiStmt(SelectionMask* mask, bool count)
590 Assert(mask);
592 std::string sql;
593 sqlite3_stmt* statement;
595 TableImplPtr table = mask->getTable();
596 Assert(table);
598 sql.append("SELECT ");
600 if(count) {
601 sql.append("COUNT(*)");
603 else
605 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
607 FieldImplPtr field = *it;
608 Assert(field);
610 if(it != table->begin())
611 sql.append(", ");
613 sql.append(field->getTable()->getName());
614 sql.append(".");
615 sql.append(field->getName());
619 sql.append(" FROM ");
620 sql.append(table->getName());
623 * Allow for queries that retreive data from foreigh tables "SELECT a, b, c, FROM Table INNER JOIN Other ON tableid = fkTable WHERE d = 5;"
625 for(Joins::const_iterator it = mask->joinsbegin(); it != mask->joinsend(); it++)
627 JoinPtr join = *it;
628 sql.append(" INNER JOIN ");
629 sql.append(join->getJoinTable()->getName());
630 sql.append(" ON ");
631 sql.append(join->getNativeKey()->getName());
632 sql.append(" = ");
633 sql.append(join->getForeignKey()->getName());
637 * Prevent queries in the form "SELECT a, b, c FROM table WHERE ;", this is for the unmasked selection.
639 if(mask->size())
640 sql.append(" WHERE ");
642 for(Strings::const_iterator it = mask->begin(); it != mask->end(); it++)
644 if(it != mask->begin())
645 sql.append(" AND ");
647 sql.append(*it);
648 sql.append("=?");
650 sql.append(";");
652 if(g_printsql) {
653 Global::Get()->printsql(sql);
656 int errorcode = sqlite3_prepare_v2(m_odb->db, sql.c_str(), (int)sql.size(), &statement, &m_leftover);
658 if(errorcode != SQLITE_OK)
659 throw SqliteError(m_odb->db, sql);
661 Assert(m_leftover == NULL || strlen(m_leftover) == 0);
663 return statement;
666 bool SqliteMgr::databasePopulated()
668 std::string sql("SELECT * FROM SQLITE_MASTER;");
670 if(g_printsql) {
671 Global::Get()->printsql(sql);
674 sqlite3_stmt* statement;
675 int errorcode = sqlite3_prepare_v2(m_odb->db, sql.c_str(), (int)sql.size(), &statement, &m_leftover);
677 if(errorcode != SQLITE_OK)
678 throw SqliteError(m_odb->db, sql);
680 Assert(m_leftover == NULL || strlen(m_leftover) == 0);
682 bool populated = doStatement(statement);
683 sqlite3_finalize(statement);
685 return populated;
688 bool SqliteMgr::tableValid(TableImplPtr table)
690 Assert(table);
692 std::string sql = tableQuery(table);
694 if(g_printsql) {
695 Global::Get()->printsql(sql);
698 sqlite3_stmt* statement;
699 int errorcode = sqlite3_prepare_v2(m_odb->db, sql.c_str(), (int)sql.size(), &statement, &m_leftover);
701 if(errorcode != SQLITE_OK)
702 throw SqliteError(m_odb->db, sql);
704 bool success = doStatement(statement);
705 sqlite3_finalize(statement);
707 return success;
710 void SqliteMgr::initTable(TableImplPtr table)
712 Assert(table);
714 std::string sql = SqliteMgr::Get()->creationQuery(table);
716 if(g_printsql) {
717 Global::Get()->printsql(sql);
720 sqlite3_stmt* statement;
721 int errorcode = sqlite3_prepare_v2(m_odb->db, sql.c_str(), (int)sql.size(), &statement, &m_leftover);
723 if(errorcode != SQLITE_OK)
724 throw SqliteError(m_odb->db, sql);
726 Assert(m_leftover == NULL || strlen(m_leftover) == 0);
727 doStatement(statement);
728 sqlite3_finalize(statement);
730 return;
733 std::string SqliteMgr::tableQuery(TableImplPtr table) const
735 Assert(table);
737 std::string result;
738 result.append("SELECT type FROM sqlite_master WHERE tbl_name='");
739 result.append(table->getName());
740 result.append("' and sql='");
742 result.append(creationQuery(table, true));
744 result.append("';");
746 return result;
750 "CREATE TABLE IF NOT EXISTS %s("
751 "%s INTEGER PRIMARY KEY AUTOINCREMENT"
752 ",versiontext TEXT"
753 ",grantgroup INTEGER RESTRAINT grantgroup DEFAULT 1"
754 ");",
756 std::string SqliteMgr::creationQuery(TableImplPtr table, bool verify) const
758 Assert(table);
760 std::string result;
762 if(verify)
763 result.append("CREATE TABLE ");
764 else
765 result.append("CREATE TABLE IF NOT EXISTS ");
767 result.append(table->getName());
768 result.append("(");
770 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
772 FieldImplPtr field = *it;
773 Assert(field);
775 bool psk = (field->isPrimaryKey() && table->primarykeysize() == 1);
777 if(it != table->begin())
778 result.append(", ");
780 result.append(field->getName());
782 if(field->isText()) {
783 result.append(" TEXT");
785 else
787 result.append(" INTEGER");
789 if(psk)
790 result.append(" PRIMARY KEY AUTOINCREMENT");
793 if(field->isLookup() && !psk)
795 result.append(" RESTRAINT ");
796 result.append(field->getName());
797 result.append(" UNIQUE");
800 std::string defaultvalue = field->getDefaultValue();
802 if(defaultvalue.size() != 0)
804 Assert(!field->isLookup());
805 Assert(!psk);
807 result.append(" RESTRAINT ");
808 result.append(field->getName());
809 result.append(" DEFAULT ");
811 if(field->isText())
812 result.append("'");
814 result.append(defaultvalue);
816 if(field->isText())
817 result.append("'");
821 if(table->primarykeysize() > 1)
823 result.append(", PRIMARY KEY(");
825 bool comspace = false;
826 for(FieldImplVector::const_iterator it = table->begin(); it != table->end(); it++)
828 FieldImplPtr field = *it;
829 Assert(field);
831 if(!field->isPrimaryKey())
832 continue;
834 if(comspace)
835 result.append(", ");
837 result.append(field->getName());
838 comspace = true;
840 result.append(")");
843 result.append(")");
845 if(!verify)
846 result.append(";");
848 return result;
851 std::string SqliteMgr::creationString(FieldImplPtr field) const
853 Assert(field);
855 std::string result = field->getName();
857 if(field->isText())
858 result.append(" TEXT");
859 else
860 result.append(" INTEGER");
862 if(field->getDefaultValue().size() != 0)
864 result.append(" RESTRAINT ");
865 result.append(field->getName());
866 result.append(" DEFAULT ");
868 if(field->isText())
869 result.append("'");
870 result.append(field->getDefaultValue());
871 if(field->isText())
872 result.append("'");
875 return result;