File indexing completed on 2024-05-12 16:40:15
0001 /* This file is part of the KDE project 0002 Copyright (C) 2004 Martin Ellis <m.a.ellis@ncl.ac.uk> 0003 Copyright (C) 2006-2016 Jarosław Staniek <staniek@kde.org> 0004 0005 This program is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This program is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this program; see the file COPYING. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "KexiSqlMigrate.h" 0022 #include <keximigratedata.h> 0023 #include <kexi.h> 0024 0025 #include <KDbDriverManager> 0026 #include <KDbConnectionProxy> 0027 #include <KDbSqlResult> 0028 #include <KDbSqlString> 0029 #include <KDbQueryColumnInfo> 0030 #include <KDbQuerySchema> 0031 0032 KexiSqlMigrate::KexiSqlMigrate(const QString &kdbDriverId, QObject *parent, 0033 const QVariantList& args) 0034 : KexiMigration::KexiMigrate(parent, args) 0035 , m_kdbDriverId(kdbDriverId) 0036 { 0037 Q_ASSERT(!m_kdbDriverId.isEmpty()); 0038 } 0039 0040 KexiSqlMigrate::~KexiSqlMigrate() 0041 { 0042 } 0043 0044 KDbConnection* KexiSqlMigrate::drv_createConnection() 0045 { 0046 KDbDriverManager manager; 0047 KDbDriver *driver = manager.driver(m_kdbDriverId); 0048 if (!driver) { 0049 m_result = manager.result(); 0050 return nullptr; 0051 } 0052 KDbConnection *c = driver->createConnection(*data()->source); 0053 m_result = c ? KDbResult() : driver->result(); 0054 return c; 0055 } 0056 0057 bool KexiSqlMigrate::drv_readTableSchema( 0058 const QString& originalName, KDbTableSchema *tableSchema) 0059 { 0060 //! @todo IDEA: ask for user input for captions 0061 0062 //Perform a query on the table to get some data 0063 KDbEscapedString sql = KDbEscapedString("SELECT * FROM %1 LIMIT 0") 0064 .arg(sourceConnection()->escapeIdentifier(tableSchema->name())); 0065 QSharedPointer<KDbSqlResult> result = sourceConnection()->prepareSql(sql); 0066 if (!result) { 0067 return false; 0068 } 0069 0070 bool ok = true; 0071 const int fieldsCount = result->fieldsCount(); 0072 for (int i = 0; i < fieldsCount; i++) { 0073 KDbField *field = result->createField(originalName, i); 0074 if (field->type() == KDbField::InvalidType) { 0075 field->setType(userType(originalName + '.' + field->name())); 0076 } 0077 if (!tableSchema->addField(field)) { 0078 delete field; 0079 tableSchema->clear(); 0080 ok = false; 0081 break; 0082 } 0083 } 0084 return ok; 0085 } 0086 0087 bool KexiSqlMigrate::drv_tableNames(QStringList *tableNames) 0088 { 0089 bool ok; 0090 *tableNames = sourceConnection()->drv_getTableNames(&ok); 0091 return ok; 0092 } 0093 0094 tristate KexiSqlMigrate::drv_queryStringListFromSql( 0095 const KDbEscapedString& sqlStatement, int fieldIndex, QStringList *stringList, int numRecords) 0096 { 0097 QSharedPointer<KDbSqlResult> result= sourceConnection()->prepareSql(sqlStatement); 0098 if (!result) { 0099 return true; 0100 } 0101 if (result->fieldsCount() < (fieldIndex+1)) { 0102 qWarning() << sqlStatement << ": fieldIndex too large (" 0103 << fieldIndex << "), expected 0.." << result->fieldsCount() - 1; 0104 return false; 0105 } 0106 for (int i = 0; numRecords == -1 || i < numRecords; i++) { 0107 QSharedPointer<KDbSqlRecord> record = result->fetchRecord(); 0108 if (!record) { 0109 if (numRecords != -1 || result->lastResult().isError()) { 0110 return false; 0111 } 0112 return true; 0113 } 0114 stringList->append(record->stringValue(fieldIndex)); 0115 } 0116 return true; 0117 } 0118 0119 bool KexiSqlMigrate::drv_copyTable(const QString& srcTable, KDbConnection *destConn, 0120 KDbTableSchema* dstTable, 0121 const RecordFilter *recordFilter) 0122 { 0123 QSharedPointer<KDbSqlResult> result = sourceConnection()->prepareSql( 0124 KDbEscapedString("SELECT * FROM %1").arg(sourceConnection()->escapeIdentifier(srcTable))); 0125 if (!result) { 0126 return false; 0127 } 0128 const KDbQueryColumnInfo::Vector fieldsExpanded(dstTable->query()->fieldsExpanded(destConn)); 0129 const int numFields = qMin(fieldsExpanded.count(), result->fieldsCount()); 0130 Q_FOREVER { 0131 QSharedPointer<KDbSqlRecord> record = result->fetchRecord(); 0132 if (!record) { 0133 if (!result->lastResult().isError()) { 0134 break; 0135 } 0136 return false; 0137 } 0138 if (recordFilter) { 0139 if (!(*recordFilter)(record)) { 0140 continue; 0141 } 0142 } 0143 QList<QVariant> vals; 0144 for(int i = 0; i < numFields; ++i) { 0145 const KDbSqlString s(record->cstringValue(i)); 0146 vals.append(KDb::cstringToVariant( 0147 s.string, fieldsExpanded.at(i)->field()->type(), 0, s.length)); 0148 } 0149 updateProgress(); 0150 if (recordFilter) { 0151 if (!(*recordFilter)(vals)) { 0152 continue; 0153 } 0154 } 0155 if (!destConn->insertRecord(dstTable, vals)) { 0156 return false; 0157 } 0158 } 0159 /*! @todo Check that wasn't an error, rather than end of result set */ 0160 return true; 0161 } 0162 0163 bool KexiSqlMigrate::drv_getTableSize(const QString& table, quint64 *size) 0164 { 0165 Q_ASSERT(size); 0166 QSharedPointer<KDbSqlResult> result 0167 = sourceConnection()->prepareSql(KDbEscapedString("SELECT COUNT(*) FROM %1") 0168 .arg(sourceConnection()->escapeIdentifier(table))); 0169 if (!result) { 0170 return false; 0171 } 0172 QSharedPointer<KDbSqlRecord> record = result->fetchRecord(); 0173 if (!result || result->fieldsCount() == 0) { 0174 return false; 0175 } 0176 bool ok; 0177 quint64 value = record->toByteArray(0).toULongLong(&ok); 0178 if (!ok) { 0179 value = -1; 0180 } 0181 *size = value; 0182 return ok; 0183 } 0184 0185 QSharedPointer<KDbSqlResult> KexiSqlMigrate::drv_readFromTable(const QString& tableName) 0186 { 0187 QSharedPointer<KDbSqlResult> result = sourceConnection()->prepareSql( 0188 KDbEscapedString("SELECT * FROM %1").arg(sourceConnection()->escapeIdentifier(tableName))); 0189 if (!result || result->lastResult().isError()) { 0190 m_result = sourceConnection()->result(); 0191 qWarning() << m_result; 0192 result.clear(); 0193 } 0194 return result; 0195 }