21#include "mysqlmigrate.h"
27#include <tqvaluelist.h>
30#include <mysql_version.h>
33#include "migration/keximigratedata.h"
34#include <kexidb/cursor.h>
35#include <kexidb/field.h>
36#include <kexidb/utils.h>
37#include <kexidb/drivers/mySQL/mysqlconnection_p.cpp>
38#include <kexidb/drivermanager.h>
39#include <kexiutils/identifier.h>
45KEXIMIGRATE_DRIVER_INFO( MySQLMigrate, mysql )
55MySQLMigrate::MySQLMigrate(TQObject *parent,
const char *name,
56 const TQStringList &args) :
58 ,d(new MySqlConnectionInternal(0))
62 m_kexiDBDriver = manager.
driver(
"mysql");
67MySQLMigrate::~MySQLMigrate() {
69 mysql_free_result(m_mysqlres);
88 return d->db_disconnect();
94bool MySQLMigrate::drv_readTableSchema(
95 const TQString& originalName, KexiDB::TableSchema& tableSchema)
103 TQString query = TQString(
"SELECT * FROM `") + drv_escapeIdentifier(originalName) +
"` LIMIT 0";
104 if(d->executeSQL(query)) {
105 MYSQL_RES *res = mysql_store_result(d->mysql);
108 unsigned int numFlds = mysql_num_fields(res);
109 MYSQL_FIELD *fields = mysql_fetch_fields(res);
111 for(
unsigned int i = 0; i < numFlds; i++) {
112 TQString fldName(fields[i].name);
116 new KexiDB::Field(fldID, type(originalName, &fields[i]));
119 TQStringList values = examineEnumField(originalName, &fields[i]);
123 getConstraints(fields[i].flags, fld);
124 getOptions(fields[i].flags, fld);
127 mysql_free_result(res);
129 kdDebug() <<
"MySQLMigrate::drv_tableNames: null result" << endl;
139bool MySQLMigrate::drv_tableNames(TQStringList& tableNames)
141 if(d->executeSQL(
"SHOW TABLES")) {
142 MYSQL_RES *res = mysql_store_result(d->mysql);
145 while ((row = mysql_fetch_row(res)) != NULL) {
146 tableNames << TQString::fromUtf8(row[0]);
148 mysql_free_result(res);
150 kdDebug() <<
"MySQLMigrate::drv_tableNames: null result" << endl;
162tristate MySQLMigrate::drv_queryStringListFromSQL(
163 const TQString& sqlStatement, uint columnNumber, TQStringList& stringList,
int numRecords)
166 if (d->executeSQL(sqlStatement)) {
167 MYSQL_RES *res = mysql_use_result(d->mysql);
169 for (
int i=0; numRecords == -1 || i < numRecords; i++) {
170 MYSQL_ROW row = mysql_fetch_row(res);
173 if (mysql_errno(d->mysql))
176 r = (numRecords == -1) ?
true : cancelled;
177 mysql_free_result(res);
180 uint numFields = mysql_num_fields(res);
181 if (columnNumber > (numFields-1)) {
182 kdWarning() <<
"MySQLMigrate::drv_querySingleStringFromSQL("<<sqlStatement
183 <<
"): columnNumber too large ("
184 << columnNumber <<
"), expected 0.." << numFields << endl;
185 mysql_free_result(res);
188 unsigned long *lengths = mysql_fetch_lengths(res);
190 mysql_free_result(res);
193 stringList.append( TQString::fromUtf8(row[columnNumber], lengths[columnNumber]) );
195 mysql_free_result(res);
197 kdDebug() <<
"MySQLMigrate::drv_querySingleStringFromSQL(): null result" << endl;
207tristate MySQLMigrate::drv_fetchRecordFromSQL(
const TQString& sqlStatement,
210 if (firstRecord || !m_mysqlres) {
212 mysql_free_result(m_mysqlres);
215 if (!d->executeSQL(sqlStatement) || !(m_mysqlres = mysql_use_result(d->mysql)))
220 MYSQL_ROW row = mysql_fetch_row(m_mysqlres);
222 tristate r = cancelled;
223 if (mysql_errno(d->mysql))
225 mysql_free_result(m_mysqlres);
229 const int numFields = mysql_num_fields(m_mysqlres);
230 unsigned long *lengths = mysql_fetch_lengths(m_mysqlres);
232 mysql_free_result(m_mysqlres);
236 data.resize(numFields);
237 for (
int i=0; i < numFields; i++)
238 data[i] = TQString::fromUtf8(row[i], lengths[i] );
243bool MySQLMigrate::drv_copyTable(
const TQString& srcTable, KexiDB::Connection *destConn,
244 KexiDB::TableSchema* dstTable)
246 if(d->executeSQL(
"SELECT * FROM `" + drv_escapeIdentifier(srcTable)) +
"`") {
247 MYSQL_RES *res = mysql_use_result(d->mysql);
250 const KexiDB::QueryColumnInfo::Vector fieldsExpanded( dstTable->
query()->
fieldsExpanded() );
251 while ((row = mysql_fetch_row(res)) != NULL) {
252 const int numFields = TQMIN((
int)fieldsExpanded.count(), (
int)mysql_num_fields(res));
253 TQValueList<TQVariant> vals;
254 unsigned long *lengths = mysql_fetch_lengths(res);
256 mysql_free_result(res);
259 for(
int i = 0; i < numFields; i++)
261 if (!destConn->insertRecord(*dstTable, vals)) {
262 mysql_free_result(res);
267 if (!row && mysql_errno(d->mysql)) {
268 mysql_free_result(res);
272 mysql_free_result(res);
274 kdDebug() <<
"MySQLMigrate::drv_copyTable: null result" << endl;
283bool MySQLMigrate::drv_getTableSize(
const TQString& table, TQ_ULLONG& size) {
284 if(d->executeSQL(
"SELECT COUNT(*) FROM `" + drv_escapeIdentifier(table)) +
"`") {
285 MYSQL_RES *res = mysql_store_result(d->mysql);
288 while ((row = mysql_fetch_row(res)) != NULL) {
290 size = TQString(row[0]).toULongLong();
292 mysql_free_result(res);
294 kdDebug() <<
"MySQLMigrate::drv_getTableSize: null result" << endl;
304 const MYSQL_FIELD *fld)
313 case FIELD_TYPE_DECIMAL:
315 case FIELD_TYPE_TINY:
318 case FIELD_TYPE_SHORT:
321 case FIELD_TYPE_LONG:
324 case FIELD_TYPE_FLOAT:
327 case FIELD_TYPE_DOUBLE:
330 case FIELD_TYPE_NULL:
332 case FIELD_TYPE_TIMESTAMP:
333 kexiType = KexiDB::Field::DateTime;
335 case FIELD_TYPE_LONGLONG:
336 case FIELD_TYPE_INT24:
339 case FIELD_TYPE_DATE:
340 kexiType = KexiDB::Field::Date;
342 case FIELD_TYPE_TIME:
343 kexiType = KexiDB::Field::Time;
345 case FIELD_TYPE_DATETIME:
346 kexiType = KexiDB::Field::DateTime;
348 case FIELD_TYPE_YEAR:
351 case FIELD_TYPE_NEWDATE:
352 case FIELD_TYPE_ENUM:
360 case FIELD_TYPE_TINY_BLOB:
361 case FIELD_TYPE_MEDIUM_BLOB:
362 case FIELD_TYPE_LONG_BLOB:
363 case FIELD_TYPE_BLOB:
364 case FIELD_TYPE_VAR_STRING:
365 case FIELD_TYPE_STRING:
367 if (fld->flags & ENUM_FLAG) {
373 kexiType = examineBlobField(table, fld);
395 const MYSQL_FIELD* fld) {
398 TQString query =
"SHOW COLUMNS FROM `" + drv_escapeIdentifier(table) +
399 "` LIKE '" + TQString::fromLatin1(fld->name) +
"'";
401 if(d->executeSQL(query)) {
402 MYSQL_RES *res = mysql_store_result(d->mysql);
406 while ((row = mysql_fetch_row(res)) != NULL) {
407 mysqlType = TQString(row[1]);
409 mysql_free_result(res);
411 kdDebug() <<
"MySQLMigrate::examineBlobField: null result" << endl;
418 kdDebug() <<
"MySQLMigrate::examineBlobField: considering "
419 << mysqlType << endl;
420 if(mysqlType.contains(
"blob",
false) != 0) {
426 }
else if(fld->length < 200) {
443TQStringList MySQLMigrate::examineEnumField(
const TQString& table,
444 const MYSQL_FIELD* fld) {
446 TQString query =
"SHOW COLUMNS FROM `" + drv_escapeIdentifier(table) +
447 "` LIKE '" + TQString::fromLatin1(fld->name) +
"'";
449 if(d->executeSQL(query)) {
450 MYSQL_RES *res = mysql_store_result(d->mysql);
454 while ((row = mysql_fetch_row(res)) != NULL) {
455 vals = TQString(row[1]);
457 mysql_free_result(res);
459 kdDebug() <<
"MySQLMigrate::examineEnumField: null result" << endl;
463 return TQStringList();
466 kdDebug() <<
"MySQLMigrate::examineEnumField: considering "
470 if(!vals.startsWith(
"enum(")) {
472 kdDebug() <<
"MySQLMigrate::examineEnumField:1 not an enum!" << endl;
473 return TQStringList();
475 if(!vals.endsWith(
")")) {
476 kdDebug() <<
"MySQLMigrate::examineEnumField:2 not an enum!" << endl;
477 return TQStringList();
483 vals = vals.remove(0,5);
484 TQRegExp rx = TQRegExp(
"^'((?:[^,']|,|'')*)'");
485 TQStringList values = TQStringList();
488 while ((index = rx.search(vals, index, TQRegExp::CaretAtOffset)) != -1) {
489 int len = rx.matchedLength();
491 kdDebug() <<
"MySQLMigrate::examineEnumField:3 " << rx.cap(1) << endl;
494 kdDebug() <<
"MySQLMigrate::examineEnumField:4 lost" << endl;
497 TQChar next = vals[index + len];
498 if (next != TQChar(
',') && next != TQChar(
')')) {
499 kdDebug() <<
"MySQLMigrate::examineEnumField:5 " << (char)next << endl;
508void MySQLMigrate::getConstraints(
int flags, KexiDB::Field* fld) {
517void MySQLMigrate::getOptions(
int flags, KexiDB::Field* fld) {
522#include "mysqlmigrate.moc"
Database driver management, e.g. finding and loading drivers.
Driver * driver(const TQString &name)
FieldList & addField(Field *field)
void setCaption(const TQString &caption)
void setPrimaryKey(bool p)
void setUniqueKey(bool u)
void setAutoIncrement(bool a)
QueryColumnInfo::Vector fieldsExpanded(FieldsExpandedOptions options=Default)
Imports non-native databases into Kexi projects.
virtual bool drv_connect()=0
Connect to source database (driver specific).
KexiMigration::Data * data() const
KexiDB::Field::Type userType(const TQString &fname)
Prompt user to select a field type for unrecognized fields.
virtual bool drv_disconnect()=0
Disconnect from source database (driver specific).
KexiMigration::Data * m_migrateData
Migrate Options.
TQVariant cstringToVariant(const char *data, KexiDB::Field *f, int length=-1)
TQValueVector< TQVariant > RowData
structure for storing single record with type information
Framework for importing databases into native KexiDB databases.
KEXIUTILS_EXPORT TQString string2Identifier(const TQString &s)