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"
30 #include "SqliteMgr.h"
31 #include "DatabaseMgr.h"
32 #include "Statements.h"
33 #include "StatementStrings.h"
36 SqliteMgr::SqliteMgr()
38 m_db
= DatabaseMgr::Get()->DB();
39 m_odb
= m_db
->grabdb();
45 SqliteMgr::~SqliteMgr()
50 void SqliteMgr::doInsert(SavableManager
* bindable
)
54 TableImpl
* table
= bindable
->getTable().get();
57 sqlite3_stmt
* insert
= getInsertStmt(table
);
60 sqlite3_reset(insert
);
62 if(table
->primarykeysize() > 1)
63 bindable
->bindKeys(m_odb
->db
, insert
);
67 if(table
->primarykeysize() == 1)
68 bindable
->parseInsert(m_odb
->db
);
73 void SqliteMgr::doErase(SavableManager
* bindable
)
77 TableImpl
* table
= bindable
->getTable().get();
80 sqlite3_stmt
* erase
= getEraseStmt(table
);
85 bindable
->bindKeys(m_odb
->db
, erase
);
91 void SqliteMgr::doUpdate(SavableManager
* bindable
)
95 TableImpl
* table
= bindable
->getTable().get();
98 // This table doesn't have any properties, it need not be updated.
99 if(table
->size() <= table
->primarykeysize())
102 sqlite3_stmt
* update
= getUpdateStmt(table
);
105 sqlite3_reset(update
);
107 bindable
->bindUpdate(m_odb
->db
, update
);
113 void SqliteMgr::doSelect(SavableManager
* bindable
)
117 TableImpl
* table
= bindable
->getTable().get();
120 sqlite3_stmt
* select
= getSelectStmt(table
);
123 sqlite3_reset(select
);
125 bindable
->bindKeys(m_odb
->db
, select
);
126 bool row
= doStatement(select
);
128 bindable
->parseSelect(select
);
130 throw RowNotFoundException("SqliteMgr::doSelect(), no row.");
133 void SqliteMgr::doLookup(SavableManager
* bindable
, FieldPtr field
)
138 TableImpl
* table
= bindable
->getTable().get();
141 sqlite3_stmt
* lookup
= getLookupStmt(table
, field
);
144 sqlite3_reset(lookup
);
146 bindable
->bindLookup(m_odb
->db
, lookup
);
147 bool row
= doStatement(lookup
);
150 bindable
->parseLookup(lookup
);
154 throw RowNotFoundException("SqliteMgr::doLookup(), no row.");
157 void SqliteMgr::doSelectMulti(SelectionMask
* mask
)
161 sqlite3_stmt
* selectMulti
= getSelectMultiStmt(mask
, false);
164 sqlite3_reset(selectMulti
);
166 mask
->bindSelectMulti(m_odb
->db
, selectMulti
);
169 for(int i
= 0; good
; i
++)
171 good
= doStatement(selectMulti
);
173 mask
->parseRow(selectMulti
);
176 sqlite3_finalize(selectMulti
);
179 void SqliteMgr::doCount(SelectionMask
* mask
)
183 sqlite3_stmt
* count
= getSelectMultiStmt(mask
, true);
186 sqlite3_reset(count
);
188 mask
->bindSelectMulti(m_odb
->db
, count
);
190 bool good
= doStatement(count
);
193 mask
->parseCount(count
);
195 sqlite3_finalize(count
);
198 void SqliteMgr::commit(TableImpl
* table
)
201 m_statements
.clear();
204 bool SqliteMgr::doStatement(sqlite3_stmt
* stmt
)
208 int rc
= sqlite3_step(stmt
);
217 throw SqliteError(m_odb
->db
);
220 StatementsPtr
SqliteMgr::getStatements(TableImpl
* table
)
224 StatementsPtr statements
= m_statements
[table
];
228 statements
= StatementsPtr(new Statements());
230 m_statements
[table
] = statements
;
234 StatementStringsPtr
SqliteMgr::getStatementStrings(TableImpl
* table
)
238 StatementStringsPtr statements
= m_statementstrings
[table
];
242 statements
= StatementStringsPtr(new StatementStrings());
244 m_statementstrings
[table
] = statements
;
248 sqlite3_stmt
* SqliteMgr::getInsertStmt(TableImpl
* table
)
252 StatementsPtr statements
= getStatements(table
);
253 sqlite3_stmt
* statement
= statements
->getInsert();
259 StatementStringsPtr statementstrings
= getStatementStrings(table
);
260 cstring statementstring
= statementstrings
->getInsert();
262 if(statementstring
.size() != 0)
264 sql
= statementstring
;
268 sql
.append("INSERT INTO ");
269 sql
.append(table
->getName());
271 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
273 FieldImplPtr field
= *it
;
276 if(!field
->isPrimaryKey())
279 if(it
!= table
->begin())
282 sql
.append(field
->getName());
284 sql
.append(") VALUES(");
285 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
287 FieldImplPtr field
= *it
;
290 if(!field
->isPrimaryKey())
293 if(it
!= table
->begin())
296 if(table
->primarykeysize() == 1)
303 statementstrings
->setInsert(sql
);
306 int errorcode
= sqlite3_prepare_v2(m_odb
->db
, sql
.c_str(), (int)sql
.size(), &statement
, &m_leftover
);
308 if(errorcode
!= SQLITE_OK
)
309 throw SqliteError(m_odb
->db
, sql
);
311 Assert(m_leftover
== NULL
|| strlen(m_leftover
) == 0);
313 statements
->setInsert(statement
);
317 sqlite3_stmt
* SqliteMgr::getEraseStmt(TableImpl
* table
)
319 StatementsPtr statements
= getStatements(table
);
320 sqlite3_stmt
* statement
= statements
->getErase();
326 StatementStringsPtr statementstrings
= getStatementStrings(table
);
327 cstring statementstring
= statementstrings
->getErase();
329 if(statementstring
.size() != 0)
331 sql
= statementstring
;
335 sql
.append("DELETE FROM ");
336 sql
.append(table
->getName());
337 sql
.append(" WHERE ");
338 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
340 FieldImplPtr field
= *it
;
343 if(!field
->isPrimaryKey())
346 if(it
!= table
->begin())
349 sql
.append(field
->getName());
354 statementstrings
->setErase(sql
);
357 int errorcode
= sqlite3_prepare_v2(m_odb
->db
, sql
.c_str(), (int)sql
.size(), &statement
, &m_leftover
);
359 if(errorcode
!= SQLITE_OK
)
360 throw SqliteError(m_odb
->db
, sql
);
362 Assert(m_leftover
== NULL
|| strlen(m_leftover
) == 0);
364 statements
->setErase(statement
);
368 sqlite3_stmt
* SqliteMgr::getUpdateStmt(TableImpl
* table
)
370 StatementsPtr statements
= getStatements(table
);
371 sqlite3_stmt
* statement
= statements
->getUpdate();
377 StatementStringsPtr statementstrings
= getStatementStrings(table
);
378 cstring statementstring
= statementstrings
->getUpdate();
380 if(statementstring
.size() != 0)
382 sql
= statementstring
;
386 sql
.append("UPDATE ");
387 sql
.append(table
->getName());
390 bool comspace
= false;
391 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
393 FieldImplPtr field
= *it
;
396 if(field
->isPrimaryKey())
402 sql
.append(field
->getName());
407 sql
.append(" WHERE ");
408 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
410 FieldImplPtr field
= *it
;
413 if(!field
->isPrimaryKey())
416 if(it
!= table
->begin())
419 sql
.append(field
->getName());
424 statementstrings
->setUpdate(sql
);
427 int errorcode
= sqlite3_prepare_v2(m_odb
->db
, sql
.c_str(), (int)sql
.size(), &statement
, &m_leftover
);
429 if(errorcode
!= SQLITE_OK
)
430 throw SqliteError(m_odb
->db
, sql
);
432 Assert(m_leftover
== NULL
|| strlen(m_leftover
) == 0);
434 statements
->setUpdate(statement
);
438 sqlite3_stmt
* SqliteMgr::getSelectStmt(TableImpl
* table
)
440 StatementsPtr statements
= getStatements(table
);
441 sqlite3_stmt
* statement
= statements
->getSelect();
447 StatementStringsPtr statementstrings
= getStatementStrings(table
);
448 cstring statementstring
= statementstrings
->getSelect();
450 if(statementstring
.size() != 0)
452 sql
= statementstring
;
456 sql
.append("SELECT ");
458 bool comspace
= false;
459 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
461 FieldImplPtr field
= *it
;
464 if(field
->isPrimaryKey())
470 sql
.append(field
->getName());
475 * Prevent queries in the form "SELECT FROM ....", this is for tables that consist of only primary keys.
477 if(table
->primarykeysize() == table
->size())
480 sql
.append(" FROM ");
481 sql
.append(table
->getName());
482 sql
.append(" WHERE ");
484 bool andspace
= false;
485 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
487 FieldImplPtr field
= *it
;
490 if(!field
->isPrimaryKey())
496 sql
.append(field
->getName());
502 statementstrings
->setSelect(sql
);
505 int errorcode
= sqlite3_prepare_v2(m_odb
->db
, sql
.c_str(), (int)sql
.size(), &statement
, &m_leftover
);
507 if(errorcode
!= SQLITE_OK
)
508 throw SqliteError(m_odb
->db
, sql
);
510 Assert(m_leftover
== NULL
|| strlen(m_leftover
) == 0);
512 statements
->setSelect(statement
);
516 sqlite3_stmt
* SqliteMgr::getLookupStmt(TableImpl
* table
, FieldPtr lookupfield
)
518 StatementsPtr statements
= getStatements(table
);
519 sqlite3_stmt
* statement
= statements
->getLookup(lookupfield
);
525 StatementStringsPtr statementstrings
= getStatementStrings(table
);
526 cstring statementstring
= statementstrings
->getLookup(lookupfield
);
528 if(statementstring
.size() != 0)
530 sql
= statementstring
;
534 sql
.append("SELECT ");
535 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
537 FieldImplPtr field
= *it
;
540 if(it
!= table
->begin())
543 sql
.append(field
->getName());
545 sql
.append(" FROM ");
546 sql
.append(table
->getName());
547 sql
.append(" WHERE ");
548 sql
.append(lookupfield
->getName());
552 statementstrings
->setLookup(lookupfield
, sql
);
555 int errorcode
= sqlite3_prepare_v2(m_odb
->db
, sql
.c_str(), (int)sql
.size(), &statement
, &m_leftover
);
557 if(errorcode
!= SQLITE_OK
)
558 throw SqliteError(m_odb
->db
, sql
);
560 Assert(m_leftover
== NULL
|| strlen(m_leftover
) == 0);
562 statements
->setLookup(lookupfield
, statement
);
566 sqlite3_stmt
* SqliteMgr::getSelectMultiStmt(SelectionMask
* mask
, bool count
)
571 sqlite3_stmt
* statement
;
573 TableImplPtr table
= mask
->getTable();
576 sql
.append("SELECT ");
579 sql
.append("COUNT(*)");
583 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
585 FieldImplPtr field
= *it
;
588 if(it
!= table
->begin())
591 sql
.append(field
->getTable()->getName());
593 sql
.append(field
->getName());
597 sql
.append(" FROM ");
598 sql
.append(table
->getName());
601 * Allow for queries that retreive data from foreigh tables "SELECT a, b, c, FROM Table INNER JOIN Other ON tableid = fkTable WHERE d = 5;"
603 for(Joins::const_iterator it
= mask
->joinsbegin(); it
!= mask
->joinsend(); it
++)
606 sql
.append(" INNER JOIN ");
607 sql
.append(join
->getJoinTable()->getName());
609 sql
.append(join
->getNativeKey()->getName());
611 sql
.append(join
->getForeignKey()->getName());
615 * Prevent queries in the form "SELECT a, b, c FROM table WHERE ;", this is for the unmasked selection.
618 sql
.append(" WHERE ");
620 for(Strings::const_iterator it
= mask
->begin(); it
!= mask
->end(); it
++)
622 if(it
!= mask
->begin())
630 int errorcode
= sqlite3_prepare_v2(m_odb
->db
, sql
.c_str(), (int)sql
.size(), &statement
, &m_leftover
);
632 if(errorcode
!= SQLITE_OK
)
633 throw SqliteError(m_odb
->db
, sql
);
635 Assert(m_leftover
== NULL
|| strlen(m_leftover
) == 0);
640 bool SqliteMgr::databasePopulated()
642 std::string
sql("SELECT * FROM SQLITE_MASTER;");
644 sqlite3_stmt
* statement
;
645 int errorcode
= sqlite3_prepare_v2(m_odb
->db
, sql
.c_str(), (int)sql
.size(), &statement
, &m_leftover
);
647 if(errorcode
!= SQLITE_OK
)
648 throw SqliteError(m_odb
->db
, sql
);
650 Assert(m_leftover
== NULL
|| strlen(m_leftover
) == 0);
652 bool populated
= doStatement(statement
);
653 sqlite3_finalize(statement
);
658 bool SqliteMgr::tableValid(TableImplPtr table
)
662 std::string sql
= tableQuery(table
);
664 sqlite3_stmt
* statement
;
665 int errorcode
= sqlite3_prepare_v2(m_odb
->db
, sql
.c_str(), (int)sql
.size(), &statement
, &m_leftover
);
667 if(errorcode
!= SQLITE_OK
)
668 throw SqliteError(m_odb
->db
, sql
);
670 bool success
= doStatement(statement
);
671 sqlite3_finalize(statement
);
676 void SqliteMgr::initTable(TableImplPtr table
)
680 std::string sql
= SqliteMgr::Get()->creationQuery(table
);
682 sqlite3_stmt
* statement
;
683 int errorcode
= sqlite3_prepare_v2(m_odb
->db
, sql
.c_str(), (int)sql
.size(), &statement
, &m_leftover
);
685 if(errorcode
!= SQLITE_OK
)
686 throw SqliteError(m_odb
->db
, sql
);
688 Assert(m_leftover
== NULL
|| strlen(m_leftover
) == 0);
689 doStatement(statement
);
690 sqlite3_finalize(statement
);
695 std::string
SqliteMgr::tableQuery(TableImplPtr table
) const
700 result
.append("SELECT type FROM sqlite_master WHERE tbl_name='");
701 result
.append(table
->getName());
702 result
.append("' and sql='");
704 result
.append(creationQuery(table
, true));
712 "CREATE TABLE IF NOT EXISTS %s("
713 "%s INTEGER PRIMARY KEY AUTOINCREMENT"
715 ",grantgroup INTEGER RESTRAINT grantgroup DEFAULT 1"
718 std::string
SqliteMgr::creationQuery(TableImplPtr table
, bool verify
) const
725 result
.append("CREATE TABLE ");
727 result
.append("CREATE TABLE IF NOT EXISTS ");
729 result
.append(table
->getName());
732 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
734 FieldImplPtr field
= *it
;
737 bool psk
= (field
->isPrimaryKey() && table
->primarykeysize() == 1);
739 if(it
!= table
->begin())
742 result
.append(field
->getName());
744 if(field
->isText()) {
745 result
.append(" TEXT");
749 result
.append(" INTEGER");
752 result
.append(" PRIMARY KEY AUTOINCREMENT");
755 if(field
->isLookup() && !psk
)
757 result
.append(" RESTRAINT ");
758 result
.append(field
->getName());
759 result
.append(" UNIQUE");
762 std::string defaultvalue
= field
->getDefaultValue();
764 if(defaultvalue
.size() != 0)
766 Assert(!field
->isLookup());
769 result
.append(" RESTRAINT ");
770 result
.append(field
->getName());
771 result
.append(" DEFAULT ");
776 result
.append(defaultvalue
);
783 if(table
->primarykeysize() > 1)
785 result
.append(", PRIMARY KEY(");
787 bool comspace
= false;
788 for(FieldImplVector::const_iterator it
= table
->begin(); it
!= table
->end(); it
++)
790 FieldImplPtr field
= *it
;
793 if(!field
->isPrimaryKey())
799 result
.append(field
->getName());
813 std::string
SqliteMgr::creationString(FieldImplPtr field
) const
817 std::string result
= field
->getName();
820 result
.append(" TEXT");
822 result
.append(" INTEGER");
824 if(field
->getDefaultValue().size() != 0)
826 result
.append(" RESTRAINT ");
827 result
.append(field
->getName());
828 result
.append(" DEFAULT ");
832 result
.append(field
->getDefaultValue());