00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "alter.h"
00021 #include "utils.h"
00022 #include <kexiutils/utils.h>
00023
00024 #include <qmap.h>
00025
00026 #include <kstaticdeleter.h>
00027
00028 #include <stdlib.h>
00029
00030 namespace KexiDB {
00031 class AlterTableHandler::Private
00032 {
00033 public:
00034 Private()
00035 {}
00036 ~Private()
00037 {}
00038 ActionList actions;
00039 QGuardedPtr<Connection> conn;
00040 };
00041 }
00042
00043 using namespace KexiDB;
00044
00046 AlterTableHandler::ChangeFieldPropertyAction nullChangeFieldPropertyAction(true);
00047 AlterTableHandler::RemoveFieldAction nullRemoveFieldAction(true);
00048 AlterTableHandler::InsertFieldAction nullInsertFieldAction(true);
00049 AlterTableHandler::MoveFieldPositionAction nullMoveFieldPositionAction(true);
00050
00051
00052
00053 AlterTableHandler::ActionBase::ActionBase(bool null)
00054 : m_alteringRequirements(0)
00055 , m_order(-1)
00056 , m_null(null)
00057 {
00058 }
00059
00060 AlterTableHandler::ActionBase::~ActionBase()
00061 {
00062 }
00063
00064 AlterTableHandler::ChangeFieldPropertyAction& AlterTableHandler::ActionBase::toChangeFieldPropertyAction()
00065 {
00066 if (dynamic_cast<ChangeFieldPropertyAction*>(this))
00067 return *dynamic_cast<ChangeFieldPropertyAction*>(this);
00068 return nullChangeFieldPropertyAction;
00069 }
00070
00071 AlterTableHandler::RemoveFieldAction& AlterTableHandler::ActionBase::toRemoveFieldAction()
00072 {
00073 if (dynamic_cast<RemoveFieldAction*>(this))
00074 return *dynamic_cast<RemoveFieldAction*>(this);
00075 return nullRemoveFieldAction;
00076 }
00077
00078 AlterTableHandler::InsertFieldAction& AlterTableHandler::ActionBase::toInsertFieldAction()
00079 {
00080 if (dynamic_cast<InsertFieldAction*>(this))
00081 return *dynamic_cast<InsertFieldAction*>(this);
00082 return nullInsertFieldAction;
00083 }
00084
00085 AlterTableHandler::MoveFieldPositionAction& AlterTableHandler::ActionBase::toMoveFieldPositionAction()
00086 {
00087 if (dynamic_cast<MoveFieldPositionAction*>(this))
00088 return *dynamic_cast<MoveFieldPositionAction*>(this);
00089 return nullMoveFieldPositionAction;
00090 }
00091
00092
00093
00094 AlterTableHandler::FieldActionBase::FieldActionBase(const QString& fieldName, int uid)
00095 : ActionBase()
00096 , m_fieldUID(uid)
00097 , m_fieldName(fieldName)
00098 {
00099 }
00100
00101 AlterTableHandler::FieldActionBase::FieldActionBase(bool)
00102 : ActionBase(true)
00103 , m_fieldUID(-1)
00104 {
00105 }
00106
00107 AlterTableHandler::FieldActionBase::~FieldActionBase()
00108 {
00109 }
00110
00111
00112
00113 static KStaticDeleter< QMap<QCString,int> > KexiDB_alteringTypeForProperty_deleter;
00114 QMap<QCString,int> *KexiDB_alteringTypeForProperty = 0;
00115
00116 int AlterTableHandler::alteringTypeForProperty(const QCString& propertyName)
00117 {
00118 if (!KexiDB_alteringTypeForProperty) {
00119 KexiDB_alteringTypeForProperty_deleter.setObject( KexiDB_alteringTypeForProperty,
00120 new QMap<QCString,int>() );
00121 #define I(name, type) \
00122 KexiDB_alteringTypeForProperty->insert(QCString(name).lower(), (int)AlterTableHandler::type)
00123 #define I2(name, type1, type2) \
00124 flag = (int)AlterTableHandler::type1|(int)AlterTableHandler::type2; \
00125 if (flag & AlterTableHandler::PhysicalAlteringRequired) \
00126 flag |= AlterTableHandler::MainSchemaAlteringRequired; \
00127 KexiDB_alteringTypeForProperty->insert(QCString(name).lower(), flag)
00128
00129
00130
00131
00132
00133
00134 int flag;
00135 I2("name", PhysicalAlteringRequired, MainSchemaAlteringRequired);
00136 I2("type", PhysicalAlteringRequired, DataConversionRequired);
00137 I("caption", MainSchemaAlteringRequired);
00138 I("description", MainSchemaAlteringRequired);
00139 I2("unsigned", PhysicalAlteringRequired, DataConversionRequired);
00140 I2("length", PhysicalAlteringRequired, DataConversionRequired);
00141 I2("precision", PhysicalAlteringRequired, DataConversionRequired);
00142 I("width", MainSchemaAlteringRequired);
00143
00144
00145 #ifdef KEXI_NO_UNFINISHED
00146
00147 I("defaultValue", MainSchemaAlteringRequired);
00148 #else
00149 I2("defaultValue", PhysicalAlteringRequired, MainSchemaAlteringRequired);
00150 #endif
00151 I2("primaryKey", PhysicalAlteringRequired, DataConversionRequired);
00152 I2("unique", PhysicalAlteringRequired, DataConversionRequired);
00153 I2("notNull", PhysicalAlteringRequired, DataConversionRequired);
00154
00155 I2("allowEmpty", PhysicalAlteringRequired, MainSchemaAlteringRequired);
00156 I2("autoIncrement", PhysicalAlteringRequired, DataConversionRequired);
00157 I2("indexed", PhysicalAlteringRequired, DataConversionRequired);
00158
00159
00160 I("visibleDecimalPlaces", ExtendedSchemaAlteringRequired);
00161
00162 #undef I
00163 #undef I2
00164 }
00165 return (*KexiDB_alteringTypeForProperty)[propertyName.lower()];
00166 }
00167
00168
00169
00170 AlterTableHandler::ChangeFieldPropertyAction::ChangeFieldPropertyAction(
00171 const QString& fieldName, const QString& propertyName, const QVariant& newValue, int uid)
00172 : FieldActionBase(fieldName, uid)
00173 , m_propertyName(propertyName)
00174 , m_newValue(newValue)
00175 {
00176 }
00177
00178 AlterTableHandler::ChangeFieldPropertyAction::ChangeFieldPropertyAction(bool)
00179 : FieldActionBase(true)
00180 {
00181 }
00182
00183 AlterTableHandler::ChangeFieldPropertyAction::~ChangeFieldPropertyAction()
00184 {
00185 }
00186
00187 void AlterTableHandler::ChangeFieldPropertyAction::updateAlteringRequirements()
00188 {
00189
00190 setAlteringRequirements( alteringTypeForProperty( m_propertyName.latin1() ) );
00191 }
00192
00193 QString AlterTableHandler::ChangeFieldPropertyAction::debugString(const DebugOptions& debugOptions)
00194 {
00195 QString s = QString("Set \"%1\" property for table field \"%2\" to \"%3\"")
00196 .arg(m_propertyName).arg(fieldName()).arg(m_newValue.toString());
00197 if (debugOptions.showUID)
00198 s.append(QString(" (UID=%1)").arg(m_fieldUID));
00199 return s;
00200 }
00201
00202 static AlterTableHandler::ActionDict* createActionDict(
00203 AlterTableHandler::ActionDictDict &fieldActions, int forFieldUID )
00204 {
00205 AlterTableHandler::ActionDict* dict = new AlterTableHandler::ActionDict(101, false);
00206 dict->setAutoDelete(true);
00207 fieldActions.insert( forFieldUID, dict );
00208 return dict;
00209 }
00210
00211 static void debugAction(AlterTableHandler::ActionBase *action, int nestingLevel,
00212 bool simulate, const QString& prependString = QString::null, QString* debugTarget = 0)
00213 {
00214 QString debugString;
00215 if (!debugTarget)
00216 debugString = prependString;
00217 if (action) {
00218 AlterTableHandler::ActionBase::DebugOptions debugOptions;
00219 debugOptions.showUID = debugTarget==0;
00220 debugOptions.showFieldDebug = debugTarget!=0;
00221 debugString += action->debugString( debugOptions );
00222 }
00223 else {
00224 if (!debugTarget)
00225 debugString += "[No action]";
00226 }
00227 if (debugTarget) {
00228 if (!debugString.isEmpty())
00229 *debugTarget += debugString + '\n';
00230 }
00231 else {
00232 KexiDBDbg << debugString << endl;
00233 #ifdef KEXI_DEBUG_GUI
00234 if (simulate)
00235 KexiUtils::addAlterTableActionDebug(debugString, nestingLevel);
00236 #endif
00237 }
00238 }
00239
00240 static void debugActionDict(AlterTableHandler::ActionDict *dict, int fieldUID, bool simulate)
00241 {
00242 QString fieldName;
00243 AlterTableHandler::ActionDictIterator it(*dict);
00244 if (dynamic_cast<AlterTableHandler::FieldActionBase*>(it.current()))
00245 fieldName = dynamic_cast<AlterTableHandler::FieldActionBase*>(it.current())->fieldName();
00246 else
00247 fieldName = "??";
00248 QString dbg = QString("Action dict for field \"%1\" (%2, UID=%3):")
00249 .arg(fieldName).arg(dict->count()).arg(fieldUID);
00250 KexiDBDbg << dbg << endl;
00251 #ifdef KEXI_DEBUG_GUI
00252 if (simulate)
00253 KexiUtils::addAlterTableActionDebug(dbg, 1);
00254 #endif
00255 for (;it.current(); ++it) {
00256 debugAction(it.current(), 2, simulate);
00257 }
00258 }
00259
00260 static void debugFieldActions(const AlterTableHandler::ActionDictDict &fieldActions, bool simulate)
00261 {
00262 #ifdef KEXI_DEBUG_GUI
00263 if (simulate)
00264 KexiUtils::addAlterTableActionDebug("** Simplified Field Actions:");
00265 #endif
00266 for (AlterTableHandler::ActionDictDictIterator it(fieldActions); it.current(); ++it) {
00267 debugActionDict(it.current(), it.currentKey(), simulate);
00268 }
00269 }
00270
00291 void AlterTableHandler::ChangeFieldPropertyAction::simplifyActions(ActionDictDict &fieldActions)
00292 {
00293 ActionDict *actionsLikeThis = fieldActions[ uid() ];
00294 if (m_propertyName=="name") {
00295
00296 QString newName( newValue().toString() );
00297
00298 ActionBase *renameActionLikeThis = actionsLikeThis ? actionsLikeThis->find( "name" ) : 0;
00299 if (dynamic_cast<ChangeFieldPropertyAction*>(renameActionLikeThis)) {
00300
00301
00302 dynamic_cast<ChangeFieldPropertyAction*>(renameActionLikeThis)->m_newValue
00303 = dynamic_cast<ChangeFieldPropertyAction*>(renameActionLikeThis)->m_newValue;
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 }
00315 else {
00316 ActionBase *removeActionForThisField = actionsLikeThis ? actionsLikeThis->find( ":remove:" ) : 0;
00317 if (removeActionForThisField) {
00318
00319
00320 }
00321 else {
00322
00323 if (!actionsLikeThis)
00324 actionsLikeThis = createActionDict( fieldActions, uid() );
00325 AlterTableHandler::ChangeFieldPropertyAction* newRenameAction
00326 = new AlterTableHandler::ChangeFieldPropertyAction( *this );
00327 KexiDBDbg << "ChangeFieldPropertyAction::simplifyActions(): insert into '"
00328 << fieldName() << "' dict:" << newRenameAction->debugString() << endl;
00329 actionsLikeThis->insert( m_propertyName.latin1(), newRenameAction );
00330 return;
00331 }
00332 }
00333 if (actionsLikeThis) {
00334
00335
00336
00337
00338 foreach_dict (ActionDictIterator, it, *actionsLikeThis) {
00339 dynamic_cast<FieldActionBase*>(it.current())->setFieldName( fieldName() );
00340 }
00341 }
00342 return;
00343 }
00344 ActionBase *removeActionForThisField = actionsLikeThis ? actionsLikeThis->find( ":remove:" ) : 0;
00345 if (removeActionForThisField) {
00346
00347 return;
00348 }
00349
00350
00351
00352
00353 ActionDict *nextActionsLikeThis = fieldActions[ uid() ];
00354 if (!nextActionsLikeThis || !nextActionsLikeThis->find( m_propertyName.latin1() )) {
00355
00356 AlterTableHandler::ChangeFieldPropertyAction* newAction
00357 = new AlterTableHandler::ChangeFieldPropertyAction( *this );
00358 if (!nextActionsLikeThis)
00359 nextActionsLikeThis = createActionDict( fieldActions, uid() );
00360 nextActionsLikeThis->insert( m_propertyName.latin1(), newAction );
00361 }
00362 }
00363
00364 bool AlterTableHandler::ChangeFieldPropertyAction::shouldBeRemoved(ActionDictDict &fieldActions)
00365 {
00366 Q_UNUSED(fieldActions);
00367 return fieldName().lower() == m_newValue.toString().lower();
00368 }
00369
00370 tristate AlterTableHandler::ChangeFieldPropertyAction::updateTableSchema(TableSchema &table, Field* field,
00371 QMap<QString, QString>& fieldMap)
00372 {
00373
00374
00375 if (SchemaAlteringRequired & alteringTypeForProperty(m_propertyName.latin1())) {
00376 bool result = KexiDB::setFieldProperty(*field, m_propertyName.latin1(), newValue());
00377 return result;
00378 }
00379
00380 if (m_propertyName=="name") {
00381 if (fieldMap[ field->name() ] == field->name())
00382 fieldMap.remove( field->name() );
00383 fieldMap.insert( newValue().toString(), field->name() );
00384 table.renameField(field, newValue().toString());
00385 return true;
00386 }
00387 return cancelled;
00388 }
00389
00392 tristate AlterTableHandler::ChangeFieldPropertyAction::execute(Connection &conn, TableSchema &table)
00393 {
00394 Q_UNUSED(conn);
00395 Field *field = table.field( fieldName() );
00396 if (!field) {
00398 return false;
00399 }
00400 bool result;
00401
00402
00403 if (SchemaAlteringRequired & alteringTypeForProperty(m_propertyName.latin1())) {
00404 result = KexiDB::setFieldProperty(*field, m_propertyName.latin1(), newValue());
00405 return result;
00406 }
00407
00408
00409 return true;
00410
00411
00412 if (m_propertyName=="name") {
00413
00414
00415
00416
00417
00418
00419
00420 }
00421 if (m_propertyName=="type") {
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 }
00432 if (m_propertyName=="length") {
00433
00434
00435 }
00436 if (m_propertyName=="primaryKey") {
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 return result;
00449 }
00450
00451
00452
00453 AlterTableHandler::RemoveFieldAction::RemoveFieldAction(const QString& fieldName, int uid)
00454 : FieldActionBase(fieldName, uid)
00455 {
00456 }
00457
00458 AlterTableHandler::RemoveFieldAction::RemoveFieldAction(bool)
00459 : FieldActionBase(true)
00460 {
00461 }
00462
00463 AlterTableHandler::RemoveFieldAction::~RemoveFieldAction()
00464 {
00465 }
00466
00467 void AlterTableHandler::RemoveFieldAction::updateAlteringRequirements()
00468 {
00470
00471 setAlteringRequirements( PhysicalAlteringRequired );
00473 }
00474
00475 QString AlterTableHandler::RemoveFieldAction::debugString(const DebugOptions& debugOptions)
00476 {
00477 QString s = QString("Remove table field \"%1\"").arg(fieldName());
00478 if (debugOptions.showUID)
00479 s.append(QString(" (UID=%1)").arg(uid()));
00480 return s;
00481 }
00482
00489 void AlterTableHandler::RemoveFieldAction::simplifyActions(ActionDictDict &fieldActions)
00490 {
00492 AlterTableHandler::RemoveFieldAction* newAction
00493 = new AlterTableHandler::RemoveFieldAction( *this );
00494 ActionDict *actionsLikeThis = fieldActions[ uid() ];
00495 if (!actionsLikeThis)
00496 actionsLikeThis = createActionDict( fieldActions, uid() );
00497 actionsLikeThis->insert( ":remove:", newAction );
00498 }
00499
00500 tristate AlterTableHandler::RemoveFieldAction::updateTableSchema(TableSchema &table, Field* field,
00501 QMap<QString, QString>& fieldMap)
00502 {
00503 fieldMap.remove( field->name() );
00504 table.removeField(field);
00505 return true;
00506 }
00507
00508 tristate AlterTableHandler::RemoveFieldAction::execute(Connection& conn, TableSchema& table)
00509 {
00510 Q_UNUSED(conn);
00511 Q_UNUSED(table);
00513 return true;
00514 }
00515
00516
00517
00518 AlterTableHandler::InsertFieldAction::InsertFieldAction(int fieldIndex, KexiDB::Field *field, int uid)
00519 : FieldActionBase(field->name(), uid)
00520 , m_index(fieldIndex)
00521 , m_field(0)
00522 {
00523 Q_ASSERT(field);
00524 setField(field);
00525 }
00526
00527 AlterTableHandler::InsertFieldAction::InsertFieldAction(const InsertFieldAction& action)
00528 : FieldActionBase(action)
00529 , m_index(action.index())
00530 {
00531 m_field = new KexiDB::Field( action.field() );
00532 }
00533
00534 AlterTableHandler::InsertFieldAction::InsertFieldAction(bool)
00535 : FieldActionBase(true)
00536 , m_index(0)
00537 , m_field(0)
00538 {
00539 }
00540
00541 AlterTableHandler::InsertFieldAction::~InsertFieldAction()
00542 {
00543 delete m_field;
00544 }
00545
00546 void AlterTableHandler::InsertFieldAction::setField(KexiDB::Field* field)
00547 {
00548 if (m_field)
00549 delete m_field;
00550 m_field = field;
00551 setFieldName(m_field ? m_field->name() : QString::null);
00552 }
00553
00554 void AlterTableHandler::InsertFieldAction::updateAlteringRequirements()
00555 {
00557
00558 setAlteringRequirements( PhysicalAlteringRequired );
00560 }
00561
00562 QString AlterTableHandler::InsertFieldAction::debugString(const DebugOptions& debugOptions)
00563 {
00564 QString s = QString("Insert table field \"%1\" at position %2")
00565 .arg(m_field->name()).arg(m_index);
00566 if (debugOptions.showUID)
00567 s.append(QString(" (UID=%1)").arg(m_fieldUID));
00568 if (debugOptions.showFieldDebug)
00569 s.append(QString(" (%1)").arg(m_field->debugString()));
00570 return s;
00571 }
00572
00585 void AlterTableHandler::InsertFieldAction::simplifyActions(ActionDictDict &fieldActions)
00586 {
00587
00588 ActionDict *actionsForThisField = fieldActions[ uid() ];
00589
00590 ActionBase *removeActionForThisField = actionsForThisField ? actionsForThisField->find( ":remove:" ) : 0;
00591 if (removeActionForThisField) {
00592
00593
00594 actionsForThisField->remove(":remove:");
00595 return;
00596 }
00597 if (actionsForThisField) {
00598
00599 QMap<QCString, QVariant> values;
00600 for (ActionDictIterator it(*actionsForThisField); it.current();) {
00601 ChangeFieldPropertyAction* changePropertyAction = dynamic_cast<ChangeFieldPropertyAction*>(it.current());
00602 if (changePropertyAction) {
00603
00604 if (changePropertyAction->propertyName()=="name") {
00605 setFieldName(changePropertyAction->newValue().toString());
00606 }
00607 values.insert( changePropertyAction->propertyName().latin1(), changePropertyAction->newValue() );
00608
00609 actionsForThisField->remove(changePropertyAction->propertyName().latin1());
00610 }
00611 else {
00612 ++it;
00613 }
00614 }
00615 if (!values.isEmpty()) {
00616
00617 KexiDB::Field *f = new KexiDB::Field( field() );
00618 if (KexiDB::setFieldProperties( *f, values )) {
00619
00620 setField( f );
00621 field().debug();
00622 #ifdef KEXI_DEBUG_GUI
00623 KexiUtils::addAlterTableActionDebug(
00624 QString("** Property-set actions moved to field definition itself:\n")+field().debugString(), 0);
00625 #endif
00626 }
00627 else {
00628 #ifdef KEXI_DEBUG_GUI
00629 KexiUtils::addAlterTableActionDebug(
00630 QString("** Failed to set properties for field ")+field().debugString(), 0);
00631 #endif
00632 KexiDBWarn << "AlterTableHandler::InsertFieldAction::simplifyActions(): KexiDB::setFieldProperties() failed!" << endl;
00633 delete f;
00634 }
00635 }
00636 }
00637
00639 AlterTableHandler::InsertFieldAction* newAction
00640 = new AlterTableHandler::InsertFieldAction( *this );
00641 if (!actionsForThisField)
00642 actionsForThisField = createActionDict( fieldActions, uid() );
00643 actionsForThisField->insert( ":insert:", newAction );
00644 }
00645
00646 tristate AlterTableHandler::InsertFieldAction::updateTableSchema(TableSchema &table, Field* field,
00647 QMap<QString, QString>& fieldMap)
00648 {
00649
00650 Q_UNUSED(field);
00652 fieldMap.remove( this->field().name() );
00653 table.insertField(index(), new Field(this->field()));
00654 return true;
00655 }
00656
00657 tristate AlterTableHandler::InsertFieldAction::execute(Connection& conn, TableSchema& table)
00658 {
00659 Q_UNUSED(conn);
00660 Q_UNUSED(table);
00662 return true;
00663 }
00664
00665
00666
00667 AlterTableHandler::MoveFieldPositionAction::MoveFieldPositionAction(
00668 int fieldIndex, const QString& fieldName, int uid)
00669 : FieldActionBase(fieldName, uid)
00670 , m_index(fieldIndex)
00671 {
00672 }
00673
00674 AlterTableHandler::MoveFieldPositionAction::MoveFieldPositionAction(bool)
00675 : FieldActionBase(true)
00676 {
00677 }
00678
00679 AlterTableHandler::MoveFieldPositionAction::~MoveFieldPositionAction()
00680 {
00681 }
00682
00683 void AlterTableHandler::MoveFieldPositionAction::updateAlteringRequirements()
00684 {
00685 setAlteringRequirements( MainSchemaAlteringRequired );
00687 }
00688
00689 QString AlterTableHandler::MoveFieldPositionAction::debugString(const DebugOptions& debugOptions)
00690 {
00691 QString s = QString("Move table field \"%1\" to position %2")
00692 .arg(fieldName()).arg(m_index);
00693 if (debugOptions.showUID)
00694 s.append(QString(" (UID=%1)").arg(uid()));
00695 return s;
00696 }
00697
00698 void AlterTableHandler::MoveFieldPositionAction::simplifyActions(ActionDictDict &fieldActions)
00699 {
00700 Q_UNUSED(fieldActions);
00702 }
00703
00704 tristate AlterTableHandler::MoveFieldPositionAction::execute(Connection& conn, TableSchema& table)
00705 {
00706 Q_UNUSED(conn);
00707 Q_UNUSED(table);
00709 return true;
00710 }
00711
00712
00713
00714 AlterTableHandler::AlterTableHandler(Connection &conn)
00715 : Object()
00716 , d( new Private() )
00717 {
00718 d->conn = &conn;
00719 }
00720
00721 AlterTableHandler::~AlterTableHandler()
00722 {
00723 delete d;
00724 }
00725
00726 void AlterTableHandler::addAction(ActionBase* action)
00727 {
00728 d->actions.append(action);
00729 }
00730
00731 AlterTableHandler& AlterTableHandler::operator<< ( ActionBase* action )
00732 {
00733 d->actions.append(action);
00734 return *this;
00735 }
00736
00737 const AlterTableHandler::ActionList& AlterTableHandler::actions() const
00738 {
00739 return d->actions;
00740 }
00741
00742 void AlterTableHandler::removeAction(int index)
00743 {
00744 d->actions.remove( d->actions.at(index) );
00745 }
00746
00747 void AlterTableHandler::clear()
00748 {
00749 d->actions.clear();
00750 }
00751
00752 void AlterTableHandler::setActions(const ActionList& actions)
00753 {
00754 d->actions = actions;
00755 }
00756
00757 void AlterTableHandler::debug()
00758 {
00759 KexiDBDbg << "AlterTableHandler's actions:" << endl;
00760 foreach_list (ActionListIterator, it, d->actions)
00761 it.current()->debug();
00762 }
00763
00764 TableSchema* AlterTableHandler::execute(const QString& tableName, ExecutionArguments& args)
00765 {
00766 args.result = false;
00767 if (!d->conn) {
00769 return 0;
00770 }
00771 if (d->conn->isReadOnly()) {
00773 return 0;
00774 }
00775 if (!d->conn->isDatabaseUsed()) {
00777 return 0;
00778 }
00779 TableSchema *oldTable = d->conn->tableSchema(tableName);
00780 if (!oldTable) {
00782 return 0;
00783 }
00784
00785 if (!args.debugString)
00786 debug();
00787
00788
00789 int allActionsCount = 0;
00790 for(ActionListIterator it(d->actions); it.current(); ++it, allActionsCount++) {
00791 it.current()->updateAlteringRequirements();
00792 it.current()->m_order = allActionsCount;
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 ActionListIterator it(d->actions);
00825
00826
00827 ActionDictDict fieldActions(3001);
00828 fieldActions.setAutoDelete(true);
00829 ActionBase* action;
00830 for(it.toLast(); (action = it.current()); --it) {
00831 action->simplifyActions( fieldActions );
00832 }
00833
00834 if (!args.debugString)
00835 debugFieldActions(fieldActions, args.simulate);
00836
00837
00838
00839 ActionVector actionsVector(allActionsCount);
00840 int currentActionsCount = 0;
00841 args.requirements = 0;
00842 QDict<char> fieldsWithChangedMainSchema(997);
00843
00844 for (ActionDictDictIterator it(fieldActions); it.current(); ++it) {
00845 for (AlterTableHandler::ActionDictIterator it2(*it.current());it2.current(); ++it2, currentActionsCount++) {
00846 if (it2.current()->shouldBeRemoved(fieldActions))
00847 continue;
00848 actionsVector.insert( it2.current()->m_order, it2.current() );
00849
00850 const int r = it2.current()->alteringRequirements();
00851 args.requirements |= r;
00852 if (r & MainSchemaAlteringRequired && dynamic_cast<ChangeFieldPropertyAction*>(it2.current())) {
00853
00854 fieldsWithChangedMainSchema.insert(
00855 dynamic_cast<ChangeFieldPropertyAction*>(it2.current())->fieldName(), (char*)1 );
00856 }
00857 }
00858 }
00859
00860 QString dbg = QString("** Overall altering requirements: %1").arg(args.requirements);
00861 KexiDBDbg << dbg << endl;
00862
00863 if (args.onlyComputeRequirements) {
00864 args.result = true;
00865 return 0;
00866 }
00867
00868 const bool recreateTable = (args.requirements & PhysicalAlteringRequired);
00869
00870 #ifdef KEXI_DEBUG_GUI
00871 if (args.simulate)
00872 KexiUtils::addAlterTableActionDebug(dbg, 0);
00873 #endif
00874 dbg = QString("** Ordered, simplified actions (%1, was %2):").arg(currentActionsCount).arg(allActionsCount);
00875 KexiDBDbg << dbg << endl;
00876 #ifdef KEXI_DEBUG_GUI
00877 if (args.simulate)
00878 KexiUtils::addAlterTableActionDebug(dbg, 0);
00879 #endif
00880 for (int i=0; i<allActionsCount; i++) {
00881 debugAction(actionsVector[i], 1, args.simulate, QString("%1: ").arg(i+1), args.debugString);
00882 }
00883
00884 if (args.requirements == 0) {
00885 args.result = true;
00886 return oldTable;
00887 }
00888 if (args.simulate) {
00889 args.result = true;
00890 return oldTable;
00891 }
00892
00893
00894
00895 TableSchema *newTable = recreateTable ? new TableSchema(*oldTable, false) : oldTable;
00896
00897 if (recreateTable) {
00898 QString tempDestTableName;
00899 while (true) {
00900 tempDestTableName = QString("%1_temp%2%3").arg(newTable->name()).arg(QString::number(rand(), 16)).arg(QString::number(rand(), 16));
00901 if (!d->conn->tableSchema(tempDestTableName))
00902 break;
00903 }
00904 newTable->setName( tempDestTableName );
00905 }
00906 oldTable->debug();
00907 if (recreateTable && !args.debugString)
00908 newTable->debug();
00909
00910
00911 int lastUID = -1;
00912 Field *currentField = 0;
00913 QMap<QString, QString> fieldMap;
00914 foreach_list( Field::ListIterator, it, newTable->fieldsIterator() ) {
00915 fieldMap.insert( it.current()->name(), it.current()->name() );
00916 }
00917 for (int i=0; i<allActionsCount; i++) {
00918 action = actionsVector[i];
00919 if (!action)
00920 continue;
00921
00922 FieldActionBase *fieldAction = dynamic_cast<FieldActionBase*>(action);
00923 if (!fieldAction) {
00924 currentField = 0;
00925 }
00926 else {
00927 if (lastUID != fieldAction->uid()) {
00928 currentField = newTable->field( fieldAction->fieldName() );
00929 lastUID = currentField ? fieldAction->uid() : -1;
00930 }
00931 InsertFieldAction *insertFieldAction = dynamic_cast<InsertFieldAction*>(action);
00932 if (insertFieldAction && insertFieldAction->index()>(int)newTable->fieldCount()) {
00933
00934 insertFieldAction->setIndex(newTable->fieldCount());
00935 }
00936 }
00937
00938
00939 args.result = action->updateTableSchema(*newTable, currentField, fieldMap);
00940 if (args.result!=true) {
00941 if (recreateTable)
00942 delete newTable;
00943 return 0;
00944 }
00945 }
00946
00947 if (recreateTable) {
00948
00949 if (!d->conn->createTable( newTable, false )) {
00950 setError(d->conn);
00951 delete newTable;
00952 args.result = false;
00953 return 0;
00954 }
00955 }
00956
00957 #if 0//todo
00958
00959 for (int i=0; i<allActionsCount; i++) {
00960 action = actionsVector[i];
00961 if (!action)
00962 continue;
00963 args.result = action->execute(*d->conn, *newTable);
00964 if (!args.result || ~args.result) {
00966 args.result = false;
00967 return 0;
00968 }
00969 }
00970 #endif
00971
00972
00973 if (!d->conn->storeExtendedTableSchemaData(*newTable)) {
00975 setError(d->conn);
00977 args.result = false;
00978 return 0;
00979 }
00980
00981 if (recreateTable) {
00982
00983
00984
00985
00986
00987
00988
00989 QString sql = QString("INSERT INTO %1 (").arg(d->conn->escapeIdentifier(newTable->name()));
00990
00991 bool first = true;
00992 QString sourceFields;
00993 foreach_list( Field::ListIterator, it, newTable->fieldsIterator() ) {
00994 Field * const f = it.current();
00995 QString renamedFieldName( fieldMap[ f->name() ] );
00996 QString sourceSQLString;
00997 if (!renamedFieldName.isEmpty()) {
00998
00999 sourceSQLString = d->conn->escapeIdentifier(renamedFieldName);
01000 }
01001 else if (!f->defaultValue().isNull()) {
01002
01006 sourceSQLString = d->conn->driver()->valueToSQL( f->type(), f->defaultValue() );
01007 }
01008 else if (f->isNotNull()) {
01009
01010 sourceSQLString = d->conn->driver()->valueToSQL(
01011 f->type(), KexiDB::emptyValueForType( f->type() ) );
01012 }
01013 else if (f->isNotEmpty()) {
01014
01015 sourceSQLString = d->conn->driver()->valueToSQL(
01016 f->type(), KexiDB::notEmptyValueForType( f->type() ) );
01017 }
01020
01021 if (!sourceSQLString.isEmpty()) {
01022 if (first) {
01023 first = false;
01024 }
01025 else {
01026 sql.append( ", " );
01027 sourceFields.append( ", " );
01028 }
01029 sql.append( d->conn->escapeIdentifier( f->name() ) );
01030 sourceFields.append( sourceSQLString );
01031 }
01032 }
01033 sql.append(QString(") SELECT ") + sourceFields + " FROM " + oldTable->name());
01034 KexiDBDbg << " ** " << sql << endl;
01035 if (!d->conn->executeSQL( sql )) {
01036 setError(d->conn);
01038 args.result = false;
01039 return 0;
01040 }
01041
01042 const QString oldTableName = oldTable->name();
01043
01044
01045
01047
01048
01049
01050
01051
01052 if (!d->conn->alterTableName(*newTable, oldTableName, true )) {
01053 setError(d->conn);
01055 args.result = false;
01056 return 0;
01057 }
01058 oldTable = 0;
01059 }
01060
01061 if (!recreateTable) {
01062 if ((MainSchemaAlteringRequired & args.requirements) && !fieldsWithChangedMainSchema.isEmpty()) {
01063
01064 foreach_list(QDictIterator<char>, it, fieldsWithChangedMainSchema) {
01065 Field *f = newTable->field( it.currentKey() );
01066 if (f) {
01067 if (!d->conn->storeMainFieldSchema(f)) {
01068 setError(d->conn);
01070 args.result = false;
01071 return 0;
01072 }
01073 }
01074 }
01075 }
01076 }
01077
01078 args.result = true;
01079 return newTable;
01080 }
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094