15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 27242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * Copyright (C) 2013 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 77242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * 1. Redistributions of source code must retain the above copyright 87242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * notice, this list of conditions and the following disclaimer. 97242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * 2. Redistributions in binary form must reproduce the above copyright 107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * notice, this list of conditions and the following disclaimer in the 117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * documentation and/or other materials provided with the distribution. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef Database_h 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define Database_h 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptWrappable.h" 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseBasicTypes.h" 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseError.h" 327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "modules/webdatabase/sqlite/SQLiteDatabase.h" 337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "platform/weborigin/SecurityOrigin.h" 347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "wtf/Deque.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/text/WTFString.h" 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 37c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 39926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class ChangeVersionData; 407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass DatabaseAuthorizer; 41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class DatabaseContext; 427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass DatabaseServer; 437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass ExecutionContext; 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SQLTransaction; 45926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class SQLTransactionBackend; 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SQLTransactionCallback; 477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass SQLTransactionClient; 487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass SQLTransactionCoordinator; 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SQLTransactionErrorCallback; 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class VoidCallback; 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass Database FINAL : public ThreadSafeRefCountedWillBeGarbageCollectedFinalized<Database>, public ScriptWrappable { 537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci DEFINE_WRAPPERTYPEINFO(); 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual ~Database(); 567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void trace(Visitor*); 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); 597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void close(); 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci PassRefPtrWillBeRawPtr<SQLTransactionBackend> runTransaction(PassRefPtrWillBeRawPtr<SQLTransaction>, bool readOnly, const ChangeVersionData*); 627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void scheduleTransactionStep(SQLTransactionBackend*); 637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void inProgressTransactionCompleted(); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionClient* transactionClient() const; 667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionCoordinator* transactionCoordinator() const; 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Direct support for the DOM API 697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String version() const; 707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void changeVersion( 717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci const String& oldVersion, 727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci const String& newVersion, 737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionCallback*, 747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionErrorCallback*, 757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci VoidCallback* successCallback); 767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void transaction( 777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionCallback*, 787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionErrorCallback*, 797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci VoidCallback* successCallback); 807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void readTransaction( 817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionCallback*, 827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionErrorCallback*, 837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci VoidCallback* successCallback); 847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool opened() const { return m_opened; } 867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool isNew() const { return m_new; } 877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SecurityOrigin* securityOrigin() const; 897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String stringIdentifier() const; 907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String displayName() const; 917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci unsigned long estimatedSize() const; 927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String fileName() const; 937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLiteDatabase& sqliteDatabase() { return m_sqliteDatabase; } 947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci unsigned long long maximumSize() const; 967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void incrementalVacuumIfNeeded(); 977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void disableAuthorizer(); 997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void enableAuthorizer(); 1007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void setAuthorizerPermissions(int); 1017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool lastActionChangedDatabase(); 1027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool lastActionWasInsert(); 1037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void resetDeletes(); 1047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool hadDeletes(); 1057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void resetAuthorizer(); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Vector<String> tableNames(); 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) void scheduleTransactionCallback(SQLTransaction*); 1097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void closeImmediately(); 1107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void closeDatabase(); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci DatabaseContext* databaseContext() const { return m_databaseContext.get(); } 1137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ExecutionContext* executionContext() const; 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprivate: 1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci class DatabaseOpenTask; 1177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci class DatabaseCloseTask; 1187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci class DatabaseTransactionTask; 1197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci class DatabaseTableNamesTask; 1207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Database(DatabaseContext*, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize); 1227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError&, String& errorMessage); 1237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void scheduleTransaction(); 1257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool getVersionFromDatabase(String& version, bool shouldCacheVersion = true); 1277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool setVersionInDatabase(const String& version, bool shouldCacheVersion = true); 1287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void setExpectedVersion(const String&); 1297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci const String& expectedVersion() const { return m_expectedVersion; } 1307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String getCachedVersion()const; 1317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void setCachedVersion(const String&); 1327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool getActualVersionForTransaction(String& version); 1337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void runTransaction( 1357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionCallback*, 1367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLTransactionErrorCallback*, 1377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci VoidCallback* successCallback, 1387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool readOnly, 1397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci const ChangeVersionData* = 0); 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Vector<String> performGetTableNames(); 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void reportOpenDatabaseResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); 1437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void reportChangeVersionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); 144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void reportStartTransactionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); 145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void reportCommitTransactionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); 1467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void reportExecuteStatementResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); 1477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void reportVacuumDatabaseResult(int sqliteErrorCode); 1487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void logErrorMessage(const String&); 1497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static const char* databaseInfoTableName(); 1507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#if !LOG_DISABLED || !ERROR_DISABLED 1517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String databaseDebugName() const { return m_contextThreadSecurityOrigin->toString() + "::" + m_name; } 1527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#endif 1537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci RefPtr<SecurityOrigin> m_contextThreadSecurityOrigin; 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<SecurityOrigin> m_databaseThreadSecurityOrigin; 1567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci RefPtrWillBeMember<DatabaseContext> m_databaseContext; // Associated with m_executionContext. 1577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String m_name; 1597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String m_expectedVersion; 1607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String m_displayName; 1617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci unsigned long m_estimatedSize; 1627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci String m_filename; 1637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci DatabaseGuid m_guid; 1657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool m_opened; 1667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool m_new; 1677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SQLiteDatabase m_sqliteDatabase; 1697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci RefPtrWillBeMember<DatabaseAuthorizer> m_databaseAuthorizer; 1717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Deque<RefPtrWillBeMember<SQLTransactionBackend> > m_transactionQueue; 1737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Mutex m_transactionInProgressMutex; 1747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool m_transactionInProgress; 1757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool m_isTransactionQueueEnabled; 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci friend class ChangeVersionWrapper; 178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) friend class DatabaseManager; 1797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci friend class SQLStatementBackend; 180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) friend class SQLTransaction; 1817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci friend class SQLTransactionBackend; 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 184c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // Database_h 187