1 /***************************************************************************
2 * Copyright (C) 2008 by Sverre Rabbelier *
3 * sverre@rabbelier.nl *
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. *
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. *
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"
29 #include "SqliteMgr.h"
30 #include "DatabaseMgr.h"
31 #include "Statements.h"
32 #include "StatementStrings.h"
36 extern bool g_printsql
;
38 SqliteMgr::SqliteMgr()
40 m_db
= DatabaseMgr::Get()->DB();
41 m_odb
= m_db
->grabdb();
47 SqliteMgr::~SqliteMgr()
52 void SqliteMgr::doInsert(SavableManager
* bindable
)
56 TableImpl
* table
= bindable
->getTable().get();
59 sqlite3_stmt
* insert
= getInsertStmt(table
);
62 sqlite3_reset(insert
);
64 if(table
->primarykeysize() > 1)
65 bindable
->bindKeys(m_odb
->db
, insert
);
69 if(table
->primarykeysize() == 1)
70 bindable
->parseInsert(m_odb
->db
);
75 void SqliteMgr::doErase(SavableManager
* bindable
)
79 TableImpl
* table
= bindable
->getTable().get();
82 sqlite3_stmt
* erase
= getEraseStmt(table
);
87 bindable
->bindKeys(m_odb
->db
, erase
);
93 void SqliteMgr::doUpdate(SavableManager
* bindable
)
97 TableImpl
* table
= bindable
->getTable().get();
100 // This table doesn't have any properties, it need not be updated.
101 if(table
->size() <= table
->primarykeysize())
104 sqlite3_stmt
* update
= getUpdateStmt(table
);
107 sqlite3_reset(update
);
109 bindable
->bindUpdate(m_odb
->db
, update
);
115 void SqliteMgr::doSelect(SavableManager
* bindable
)
119 TableImpl
* table
= bindable
->getTable().get();
122 sqlite3_stmt
* select
= getSelectStmt(table
);
125 sqlite3_reset(select
);
127 bindable
->bindKeys(m_odb
->db
, select
);
128 bool row
= doStatement(select
);
130 bindable
->parseSelect(select
);
132 throw RowNotFoundException("SqliteMgr::doSelect(), no row.");
135 void SqliteMgr::doLookup(SavableManager
* bindable
, FieldPtr field
)
140 TableImpl
* table
= bindable
->getTable().get();
143 sqlite3_stmt
* lookup
= getLookupStmt(table
, field
);
146 sqlite3_reset(lookup
);
148 bindable
->bindLookup(m_odb
->db
, lookup
);
149 bool row
= doStatement(lookup
);
152 bindable
->parseLookup(lookup
);
156 throw RowNotFoundException("SqliteMgr::doLookup(), no row.");
159 void SqliteMgr::doSelectMulti(SelectionMask
* mask
)
163 sqlite3_stmt
* selectMulti
= getSelectMultiStmt(mask
, false);
166 sqlite3_reset(selectMulti
);
168 mask
->bindSelectMulti(m_odb
->db
, selectMulti
);
171 for(int i
= 0; good
; i
++)
173 good
= doStatement(selectMulti
);
175 mask
->parseRow(selectMulti
);
178 sqlite3_finalize(selectMulti
);
181 void SqliteMgr::doCount(SelectionMask
* mask
)
185 sqlite3_stmt
* count
= getSelectMultiStmt(mask
, true);
188 sqlite3_reset(count
);
190 mask
->bindSelectMulti(m_odb
->db
, count
);
192 bool good
= doStatement(count
);
195 mask
->parseCount(count
);
197 sqlite3_finalize(count
);
200 void SqliteMgr::commit(TableImpl
* table
)
203 m_statements
.clear();
206 bool SqliteMgr::doStatement(sqlite3_stmt
* stmt
)
210 int rc
= sqlite3_step(stmt
);
219 throw SqliteError(m_odb
->db
);
222 StatementsPtr
SqliteMgr::getStatements(TableImpl
* table
)
226 StatementsPtr statements
= m_statements
[table
];
230 statements
= StatementsPtr(new Statements());
232 m_statements
[table
] = statements
;
236 StatementStringsPtr
SqliteMgr::getStatementStrings(TableImpl
* table
)
240 StatementStringsPtr statements
= m_statementstrings
[table
];
244 statements
= StatementStringsPtr(new StatementStrings());
246 m_statementstrings
[table
] = statements
;
250 sqlite3_stmt
* SqliteMgr::getInsertStmt(TableImpl
* table
)
254 StatementsPtr statements
= getStatements(table
);
255 sqlite3_stmt
* statement
= statements
->getInsert();
261 StatementStringsPtr statementstrings
= getStatementStrings(table
);
262 cstring statementstring
= statementstrings
->getInsert();
264 if(statementstring
.size() != 0)
266 sql
= statementstring
;
270 sql
.append("INSERT INTO ");
271 sql
.append(table
->getName());
273 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
275 FieldImplPtr field
= *it
;
278 if(!field
->isPrimaryKey())
281 if(it
!= table
->begin())
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
;
292 if(!field
->isPrimaryKey())
295 if(it
!= table
->begin())
298 if(table
->primarykeysize() == 1)
305 statementstrings
->setInsert(sql
);
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
);
323 sqlite3_stmt
* SqliteMgr::getEraseStmt(TableImpl
* table
)
325 StatementsPtr statements
= getStatements(table
);
326 sqlite3_stmt
* statement
= statements
->getErase();
332 StatementStringsPtr statementstrings
= getStatementStrings(table
);
333 cstring statementstring
= statementstrings
->getErase();
335 if(statementstring
.size() != 0)
337 sql
= statementstring
;
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
;
349 if(!field
->isPrimaryKey())
352 if(it
!= table
->begin())
355 sql
.append(field
->getName());
360 statementstrings
->setErase(sql
);
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
);
378 sqlite3_stmt
* SqliteMgr::getUpdateStmt(TableImpl
* table
)
380 StatementsPtr statements
= getStatements(table
);
381 sqlite3_stmt
* statement
= statements
->getUpdate();
387 StatementStringsPtr statementstrings
= getStatementStrings(table
);
388 cstring statementstring
= statementstrings
->getUpdate();
390 if(statementstring
.size() != 0)
392 sql
= statementstring
;
396 sql
.append("UPDATE ");
397 sql
.append(table
->getName());
400 bool comspace
= false;
401 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
403 FieldImplPtr field
= *it
;
406 if(field
->isPrimaryKey())
412 sql
.append(field
->getName());
417 sql
.append(" WHERE ");
418 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
420 FieldImplPtr field
= *it
;
423 if(!field
->isPrimaryKey())
426 if(it
!= table
->begin())
429 sql
.append(field
->getName());
434 statementstrings
->setUpdate(sql
);
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
);
452 sqlite3_stmt
* SqliteMgr::getSelectStmt(TableImpl
* table
)
454 StatementsPtr statements
= getStatements(table
);
455 sqlite3_stmt
* statement
= statements
->getSelect();
461 StatementStringsPtr statementstrings
= getStatementStrings(table
);
462 cstring statementstring
= statementstrings
->getSelect();
464 if(statementstring
.size() != 0)
466 sql
= statementstring
;
470 sql
.append("SELECT ");
472 bool comspace
= false;
473 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
475 FieldImplPtr field
= *it
;
478 if(field
->isPrimaryKey())
484 sql
.append(field
->getName());
489 * Prevent queries in the form "SELECT FROM ....", this is for tables that consist of only primary keys.
491 if(table
->primarykeysize() == table
->size())
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
;
504 if(!field
->isPrimaryKey())
510 sql
.append(field
->getName());
516 statementstrings
->setSelect(sql
);
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
);
534 sqlite3_stmt
* SqliteMgr::getLookupStmt(TableImpl
* table
, FieldPtr lookupfield
)
536 StatementsPtr statements
= getStatements(table
);
537 sqlite3_stmt
* statement
= statements
->getLookup(lookupfield
);
543 StatementStringsPtr statementstrings
= getStatementStrings(table
);
544 cstring statementstring
= statementstrings
->getLookup(lookupfield
);
546 if(statementstring
.size() != 0)
548 sql
= statementstring
;
552 sql
.append("SELECT ");
553 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
555 FieldImplPtr field
= *it
;
558 if(it
!= table
->begin())
561 sql
.append(field
->getName());
563 sql
.append(" FROM ");
564 sql
.append(table
->getName());
565 sql
.append(" WHERE ");
566 sql
.append(lookupfield
->getName());
570 statementstrings
->setLookup(lookupfield
, sql
);
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
);
588 sqlite3_stmt
* SqliteMgr::getSelectMultiStmt(SelectionMask
* mask
, bool count
)
593 sqlite3_stmt
* statement
;
595 TableImplPtr table
= mask
->getTable();
598 sql
.append("SELECT ");
601 sql
.append("COUNT(*)");
605 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
607 FieldImplPtr field
= *it
;
610 if(it
!= table
->begin())
613 sql
.append(field
->getTable()->getName());
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
++)
628 sql
.append(" INNER JOIN ");
629 sql
.append(join
->getJoinTable()->getName());
631 sql
.append(join
->getNativeKey()->getName());
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.
640 sql
.append(" WHERE ");
642 for(Strings::const_iterator it
= mask
->begin(); it
!= mask
->end(); it
++)
644 if(it
!= mask
->begin())
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);
666 bool SqliteMgr::databasePopulated()
668 std::string
sql("SELECT * FROM SQLITE_MASTER;");
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
);
688 bool SqliteMgr::tableValid(TableImplPtr table
)
692 std::string sql
= tableQuery(table
);
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
);
710 void SqliteMgr::initTable(TableImplPtr table
)
714 std::string sql
= SqliteMgr::Get()->creationQuery(table
);
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
);
733 std::string
SqliteMgr::tableQuery(TableImplPtr table
) const
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));
750 "CREATE TABLE IF NOT EXISTS %s("
751 "%s INTEGER PRIMARY KEY AUTOINCREMENT"
753 ",grantgroup INTEGER RESTRAINT grantgroup DEFAULT 1"
756 std::string
SqliteMgr::creationQuery(TableImplPtr table
, bool verify
) const
763 result
.append("CREATE TABLE ");
765 result
.append("CREATE TABLE IF NOT EXISTS ");
767 result
.append(table
->getName());
770 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
772 FieldImplPtr field
= *it
;
775 bool psk
= (field
->isPrimaryKey() && table
->primarykeysize() == 1);
777 if(it
!= table
->begin())
780 result
.append(field
->getName());
782 if(field
->isText()) {
783 result
.append(" TEXT");
787 result
.append(" INTEGER");
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());
807 result
.append(" RESTRAINT ");
808 result
.append(field
->getName());
809 result
.append(" DEFAULT ");
814 result
.append(defaultvalue
);
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
;
831 if(!field
->isPrimaryKey())
837 result
.append(field
->getName());
851 std::string
SqliteMgr::creationString(FieldImplPtr field
) const
855 std::string result
= field
->getName();
858 result
.append(" TEXT");
860 result
.append(" INTEGER");
862 if(field
->getDefaultValue().size() != 0)
864 result
.append(" RESTRAINT ");
865 result
.append(field
->getName());
866 result
.append(" DEFAULT ");
870 result
.append(field
->getDefaultValue());