File indexing completed on 2024-05-12 16:40:15
0001 /* This file is part of the KDE project 0002 Copyright (C) 2004 Adam Pigg <adam@piggz.co.uk> 0003 Copyright (C) 2004-2016 Jarosław Staniek <staniek@kde.org> 0004 Copyright (C) 2005 Martin Ellis <martin.ellis@kdemail.net> 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This program is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this program; see the file COPYING. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #ifndef KEXI_MIGRATE_H 0023 #define KEXI_MIGRATE_H 0024 0025 #include "keximigratedata.h" 0026 #include "KexiVersion.h" 0027 0028 #include <KDbConnection> 0029 #include <KDbSqlRecord> 0030 #include <KDbTableSchema> 0031 0032 #include <QVariantList> 0033 0034 class KDbConnectionProxy; 0035 0036 namespace Kexi 0037 { 0038 class ObjectStatus; 0039 } 0040 class KexiMigratePluginMetaData; 0041 0042 /*! KexiMigration implementation version. 0043 It is altered after every change: 0044 - major number is increased after incompatible change ofthe plugin interface/behavior 0045 - minor number is increased after minor changes 0046 @note Do not use these constants to get library version information in external code. 0047 Use KexiMigratePluginMetaData::*version() functions instead. 0048 */ 0049 #define KEXI_MIGRATION_VERSION_MAJOR KEXI_STABLE_VERSION_MAJOR 0050 #define KEXI_MIGRATION_VERSION_MINOR KEXI_STABLE_VERSION_MINOR 0051 0052 /*! 0053 * \namespace KexiMigration 0054 * \brief Framework for importing databases into native KDb databases. 0055 */ 0056 namespace KexiMigration 0057 { 0058 0059 //! \return KexiMigration library version info 0060 KEXIMIGRATE_EXPORT KDbVersionInfo version(); 0061 0062 //! @short A base class for a migrate plugin that imports native databases into Kexi projects 0063 /*! A generic API for importing schema and data from an existing 0064 database into a new Kexi project. Can be also used for importing native Kexi databases. 0065 0066 Basic idea is this: 0067 -# User selects an existing DB and new project (file or server based) 0068 -# User specifies whether to import structure and data or structure only. 0069 -# Import tool connects to db 0070 -# Checks if it is already a kexi project (not implemented yet) 0071 -# If not, then read structure and construct new project 0072 -# Ask user what to do if column type is not supported 0073 0074 See kexi/doc/dev/kexi_import.txt for more info. 0075 */ 0076 class KEXIMIGRATE_EXPORT KexiMigrate : public QObject, public KDbResultable 0077 { 0078 Q_OBJECT 0079 0080 public: 0081 virtual ~KexiMigrate(); 0082 0083 //! Info about the driver's plugin 0084 const KexiMigratePluginMetaData* metaData() const; 0085 0086 //! @todo Remove this! KexiMigrate should be usable for multiple concurrent migrations! 0087 KexiMigration::Data* data(); 0088 0089 //! @todo Remove this! KexiMigrate should be usable for multiple concurrent migrations! 0090 //! Data Setup. Requires two connection objects, a name and a bool 0091 //! Ownership of @a migrateData is transferred to the KexiMigrate object. 0092 //! Any previous data is removed if it is different than @a migrateData. 0093 void setData(KexiMigration::Data* migrateData); 0094 0095 /*! Checks whether the destination database exists. 0096 For file-based dest. projects, we've already asked about overwriting 0097 existing project but for server-based projects it's better to ask user. 0098 This method should be called before performImport() or performExport(). 0099 0100 \return true if no connection-related errors occurred. 0101 \a acceptingNeeded is set to true if destination database exists. 0102 In this case you should ask about accepting database overwriting. 0103 Used in ImportWizard::import(). */ 0104 bool checkIfDestinationDatabaseOverwritingNeedsAccepting(Kexi::ObjectStatus* result, 0105 bool* acceptingNeeded); 0106 0107 /*! Checks if the source- and the destination databases are identical. 0108 \return true if they are identical else false. */ 0109 bool isSourceAndDestinationDataSourceTheSame() const; 0110 0111 //! Connects, perform an import operation, and disconnects 0112 bool performImport(Kexi::ObjectStatus* result = 0); 0113 0114 //! Perform an export operation 0115 bool performExport(Kexi::ObjectStatus* result = 0); 0116 0117 //! Returns true if the migration driver supports progress updates. 0118 inline bool progressSupported() { 0119 return drv_progressSupported(); 0120 } 0121 0122 //! @todo This is copied from KDbDriver. One day it will be merged with KDb. 0123 //! \return property value for \a propertyName available for this driver. 0124 //! If there's no such property defined for driver, Null QVariant value is returned. 0125 virtual QVariant propertyValue(const QByteArray& propertyName); 0126 0127 //! @todo This is copied from KDbDriver. One day it will be merged with KDb. 0128 void setPropertyValue(const QByteArray& propertyName, const QVariant& value); 0129 0130 //! @todo This is copied from KDbDriver. One day it will be merged with KDb. 0131 //! \return translated property caption for \a propertyName. 0132 //! If there's no such property defined for driver, empty string value is returned. 0133 QString propertyCaption(const QByteArray& propertyName) const; 0134 0135 //! @todo This is copied from KDbDriver. One day it will be merged with KDb. 0136 //! Set translated property caption for \a propertyName. 0137 void setPropertyCaption(const QByteArray& propertyName, const QString &caption); 0138 0139 //! @todo This is copied from KDbDriver. One day it will be merged with KDb. 0140 //! \return a list of property names available for this driver. 0141 QList<QByteArray> propertyNames() const; 0142 0143 //! Extension of existing API to provide generic row access to external data for ImportTableWizard. 0144 //! @todo refactor 0145 bool connectSource(Kexi::ObjectStatus* result); 0146 0147 //! Extension of existing API to close connection for ImportTableWizard. 0148 //! @todo refactor 0149 bool disconnectSource(); 0150 0151 //! Get table names in source database (driver specific) 0152 bool tableNames(QStringList *tablenames); 0153 0154 //! Read schema for a given table (driver specific) 0155 bool readTableSchema(const QString& originalName, KDbTableSchema *tableSchema); 0156 0157 //! Starts reading data from the source dataset's table 0158 QSharedPointer<KDbSqlResult> readFromTable(const QString& tableName); 0159 0160 //!Move to the next row 0161 bool moveNext(); 0162 0163 //!Move to the previous row 0164 bool movePrevious(); 0165 0166 //!Move to the next row 0167 bool moveFirst(); 0168 0169 //!Move to the previous row 0170 bool moveLast(); 0171 0172 //!Read the data at the given row/field 0173 QVariant value(int i); 0174 0175 Q_SIGNALS: 0176 void progressPercent(int percent); 0177 0178 protected: 0179 //! Used by MigrateManager. 0180 explicit KexiMigrate(QObject *parent, const QVariantList &args = QVariantList()); 0181 0182 /*! Used by the migration driver manager to set metaData for just loaded driver. */ 0183 void setMetaData(const KexiMigratePluginMetaData *metaData); 0184 0185 //! Creates connection to source database and connects. 0186 //! If it is a database supported by low-level routines of KDb, sourceConnection() will 0187 //! be available afterwards. 0188 //! If not, connectInternal() can still return true but sourceConnection() will return 0189 //! @c nullptr. 0190 //! @see drv_createConnection() drv_connect() 0191 bool connectInternal(Kexi::ObjectStatus* result); 0192 0193 //! Disconnects from source database. If it is a database supported by low-level routines 0194 //! of KDb, destroys the connection object pointed by sourceConnection() too. 0195 //! @return true on success. 0196 //! @see drv_disconnect() connectInternal() 0197 bool disconnectInternal(); 0198 0199 //! @return connection to source database if it is a database supported by low-level 0200 //! routines of KDb. In other cases such as importing from a TSV file, this function 0201 //! returns @c nullptr. 0202 KDbConnectionProxy* sourceConnection(); 0203 0204 //! Migration drivers that use low-level routines KDb to access the source database 0205 //! should create and return a driver-specific KDbConnection object that handles 0206 //! connection to the source database. 0207 //! Migration drivers that use custom data sources (not KDb-compatible) should return 0208 //! @c nullptr. 0209 //! @note KexiMigrate::m_result should be set to a result of the operation. 0210 virtual KDbConnection* drv_createConnection() = 0; 0211 0212 //! Connects to source database using (driver specific). 0213 //! Default implementation calls sourceConnection()->drv_connect() and if it succeeds, 0214 //! it calls sourceConnection()->drv_useDatabase(data()->sourceName), then returns 0215 //! the result. If this is enough for connecting for a migration driver, there is no need 0216 //! to reimplement drv_connect(). 0217 //! If sourceConnection() is @c nullptr (custom types of sources), 0218 //! default implementation just returns @c false. In this case drv_connect() should 0219 //! be implemented. 0220 virtual bool drv_connect(); 0221 0222 //! Disconnect from source database (driver specific). 0223 //! If the source database is supported by low-level routines KDb, 0224 //! KDbConnection::disconnect() is called for this connection. 0225 //! For other types of sources @c false is returned so in these cases this method 0226 //! should be reimplemented. 0227 virtual bool drv_disconnect(); 0228 0229 //! Get table names in source database (driver specific) 0230 /*! @return List of table names available for this connection. 0231 The names are in lower case. The method should return true only if there was no 0232 error on getting database names list from the server. */ 0233 virtual bool drv_tableNames(QStringList *tablenames) = 0; 0234 0235 //! Read schema for a given table (driver specific) 0236 virtual bool drv_readTableSchema( 0237 const QString& originalName, KDbTableSchema *tableSchema) = 0; 0238 0239 /*! Fetches maximum number from table \a tableName, column \a columnName 0240 into \a result. On success true is returned. If there is no records in the table, 0241 \a result is set to 0 and true is returned. 0242 - Note 1: implement only if the database can already contain kexidb__* tables 0243 (so e.g. keximdb driver doea not need this). 0244 - Note 2: default implementation uses drv_querySingleStringFromSql() 0245 with "SELECT MAX(columName) FROM tableName" statement, assuming SQL-compliant 0246 backend. 0247 */ 0248 virtual bool drv_queryMaxNumber(const QString& tableName, 0249 const QString& columnName, int *result); 0250 0251 /*! Fetches single string at column \a columnNumber for each record from result obtained 0252 by running \a sqlStatement. \a numRecords can be specified to limit number of records read. 0253 If \a numRecords is -1, all records are loaded. 0254 On success the result is stored in \a stringList and true is returned. 0255 \return cancelled if there are no records available. 0256 - Note: implement only if the database can already contain kexidb__* tables 0257 (so e.g. keximdb driver does not need this). */ 0258 //! @todo SQL-dependent! 0259 virtual tristate drv_queryStringListFromSql( 0260 const KDbEscapedString& sqlStatement, int columnNumber, QStringList *stringList, 0261 int numRecords = -1) 0262 { 0263 Q_UNUSED(sqlStatement); Q_UNUSED(columnNumber); Q_UNUSED(stringList); 0264 Q_UNUSED(numRecords); 0265 return cancelled; 0266 } 0267 0268 /*! Fetches single string at column \a columnNumber from result obtained 0269 by running \a sqlStatement. 0270 On success the result is stored in \a string and true is returned. 0271 \return cancelled if there are no records available. 0272 This implementation uses drv_queryStringListFromSql() with numRecords == 1. */ 0273 //! @todo SQL-dependent! 0274 virtual tristate drv_querySingleStringFromSql(const KDbEscapedString& sqlStatement, 0275 int columnNumber, QString *string); 0276 0277 //! A functor for filtering records 0278 //! @see drv_copyTable() 0279 class RecordFilter { 0280 public: 0281 RecordFilter() {} 0282 virtual ~RecordFilter() {} 0283 virtual bool operator() (const QSharedPointer<KDbSqlRecord> &record) const = 0; 0284 virtual bool operator() (const QList<QVariant> &record) const = 0; 0285 }; 0286 0287 //! Copy a table from source DB to target DB (driver specific) 0288 //! - create copies of KDb tables 0289 //! - create copies of non-KDb tables 0290 virtual bool drv_copyTable(const QString& srcTable, KDbConnection *destConn, 0291 KDbTableSchema* dstTable, 0292 const RecordFilter *recordFilter = nullptr) = 0; 0293 0294 virtual bool drv_progressSupported() { 0295 return false; 0296 } 0297 0298 /*! \return the size of a table to be imported, or 0 if not supported 0299 Finds the size of the named table, in order to provide feedback on 0300 migration progress. 0301 0302 The units of the return type are deliberately unspecified. Migration 0303 drivers may return the number of records in the table, or the size in 0304 bytes, etc. Units should be chosen in order that the driver can 0305 return the size in the fastest way possible (e.g. migration from CSV 0306 files should use file size to avoid counting the number of rows, and 0307 migration from MDB files should return the number of rows as this is 0308 stored within the file). 0309 0310 Obviously, the driver should use the same units when reporting 0311 migration progress. 0312 0313 \return size of the specified table 0314 */ 0315 virtual bool drv_getTableSize(const QString&, quint64*) { 0316 return false; 0317 } 0318 0319 void updateProgress(quint64 step = 1ULL); 0320 0321 //! @todo user should be asked ONCE using a convenient wizard's page, not a popup dialog 0322 //! Prompt user to select a field type for unrecognized fields 0323 KDbField::Type userType(const QString& fname); 0324 0325 virtual QString drv_escapeIdentifier(const QString& str) const; 0326 0327 //Extended API 0328 //! Position the source dataset at the start of a table 0329 virtual QSharedPointer<KDbSqlResult> drv_readFromTable(const QString & tableName) { 0330 Q_UNUSED(tableName); 0331 return QSharedPointer<KDbSqlResult>(); 0332 } 0333 0334 //! Move to the next row 0335 virtual bool drv_moveNext() { return false; } 0336 0337 //! Move to the previous row 0338 virtual bool drv_movePrevious() { return false; } 0339 0340 //! Move to the next row 0341 virtual bool drv_moveFirst() { return false; } 0342 0343 //! Move to the previous row 0344 virtual bool drv_moveLast() { return false; } 0345 0346 //! Read the data at the given row/field 0347 virtual QVariant drv_value(int i) { Q_UNUSED(i); return QVariant(); }; 0348 0349 //! @return Database driver for this migration. 0350 KDbDriver *driver(); 0351 0352 //! Sets database driver for this migration. 0353 void setDriver(KDbDriver *driver); 0354 0355 private: 0356 /*! Estimate size of migration job 0357 Calls drv_getTableSize for each table to be copied. 0358 \return sum of the size of all tables to be copied. 0359 */ 0360 bool progressInitialise(); 0361 0362 //! Perform an import operation. It is assumed that source connection is established. 0363 //! @see performImport() 0364 bool performImportInternal(Kexi::ObjectStatus* result); 0365 0366 //! Reads schema for table @a tableName from kexi__objects and kexi__fields. 0367 //! On success: 0368 //! - copies one record from the original kexi__objects table to the destination 0369 //! database's table kexi__objects 0370 //! - copies all related records from the original kexi__fields table to the destination 0371 //! database's table kexi__fields 0372 bool importTable(const QString& tableName, KDbConnectionProxy *destConn); 0373 0374 class Private; 0375 Private * const d; 0376 0377 friend class MigrateManager; 0378 friend class MigrateManagerInternal; 0379 }; 0380 0381 } //namespace KexiMigration 0382 0383 #endif