/* FMainRecord тот самый компонент на базе TList о котором говорилось в теме Как динамически создать .... Кроме прочих есть методы GetAllFields(DataSet) всасыват все текущие значения полей UpdateBody([список полей]) генерит тест тела sql команды Update InsertBody([список полей]) генерит тест тела sql команды Insert Вариант для нехешированных изменений. Есть и для хешированных. Нужно будет - покажу */ //--------------------------------------------------------------------------- // Перехватить и отменить Post и отработать его в DS->StateChange // текущее состояние полей в FMainRecord //--------------------------------------------------------------------------- void __fastcall TF_UniEdit::QryMainBeforePost(TDataSet *DataSet) { if (QryMain->State == dsEdit) FAbortPostState = 2; else if (QryMain->State == dsInsert) FAbortPostState = 3; else { FAbortPostState = 0; QryMain->Cancel(); Abort(); } //FMainRecord->GetAllFieldsOld(QryMain); //FQryMain_PK_Old = FMainRecord->ByName(FQryMain_PKName)->AsInteger; FMainRecord->GetAllFields(QryMain); FQryMain_PK = FMainRecord->ByName(FQryMain_PKName)->AsInteger; /* ShowMessage (AnsiString("") + "FAbortPostState = " + AnsiString(FAbortPostState) + "\n" + "FQryMain_PK = " + AnsiString(FQryMain_PK) + "\n" + "FQryMain_PK_Old = " + AnsiString(FQryMain_PK_Old) + "\n" + "" ); */ PrepareBaseTable_FieldsList(); TAxField *fax; TBlobField *fld; for (int i=0; i < FQM_BlobFields->Count; i++) { fax = FQM_BlobFields->Items[i]; fld = dynamic_cast(QryMain->FindField(fax->Name)); fax->NeedInSQL = fld && fld->Modified;; } QryMain->Cancel(); Abort(); } //--------------------------------------------------------------------------- // Изменилось состояние ... Browse <-> Edit ... //--------------------------------------------------------------------------- void __fastcall TF_UniEdit::DSr_MainStateChange(TObject *Sender) { SetToolBars (); if (QryMain->State == dsEdit && (FQMPreviosState == dsBrowse || FQMPreviosState == dsInsert) ) { QryMain_RecordPrepareEdit(); return; } if (QryMain->State != dsBrowse) { FQMPreviosState = QryMain->State; return; } // Обработка отложенного Post'a int state = FAbortPostState; FAbortPostState = 0; if (state == 2) QryMain_PostEdit (); // Post Edit else if (state == 3) QryMain_PostInsert (); // Post Insert else ; FQMPreviosState = QryMain->State; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void __fastcall TF_UniEdit::QryMain_PostEdit (void) // Save Edit { // Новые данные зачитаны в FMainRecord функцией (QryMainBeforePost) Grd_Main->SetFocus(); if (FQryMain_PK == 0) return; // Рассчет списка полей для Update на базе анализа списка полей базовой таблици if (FBaseTable_FieldsList.IsEmpty()) PrepareBaseTable_FieldsList(); if (FBaseTable_FieldsList.IsEmpty()) FBaseTable_FieldsList = "Null"; if (FBaseTable_FieldsList == "Null") { OEMessage_Show("При сохранении изменений не удалось получить список полей базовой таблици."); return; } TAxRecord *trec = FTmpRecord; trec->FullClear(); trec->UpdAdd(FMainRecord, FBaseTable_FieldsList); trec->SetAllReadOnly (false, FQryMain_PKName); trec->SetAllNeedInSQL(false, "Created_On, Ctreated_By, Changed_On, Changed_By"); if (FQryMain_PK != FQryMain_PK_Old) { TAxField *fax = trec->ByName(FQryMain_PKName); if (fax) fax->ReadOnly = false; } // RecordInfo(trec); // edit_marker 7 AnsiString sqltext = AnsiString("") + "Update " + FBaseTable + "\n" + " Set" + trec->UpdateBody() + " Where " + FQryMain_PKName + " = " + AnsiString(FQryMain_PK_Old); /* ShowMessage (AnsiString("") + "FQryMain_PK = " + AnsiString(FQryMain_PK) + "\n" + "FQryMain_PK_Old = " + AnsiString(FQryMain_PK_Old) + "\n" + sqltext ); */ TAxRecord *wrec = FWrkRecord; wrec->FullClear(); AnsiString act_info = ""; if (FAct_Update) { wrec->GetAllFieldsOld(QryMain); act_info = AnsiString("Upd ") + FBaseTable_Name + ": " + "ID=" + AnsiString(FQryMain_PK); AnsiString nstr, ostr; bool b; for (int i=0; i < trec->Count; i++) { if (trec->Items[i]->ReadOnly) continue; try { nstr = trec->Items[i]->AsString; ostr = wrec->ByName(trec->Items[i]->Name)->AsString; b = true; } catch (...) { b = false; } if (!b || nstr == ostr) continue; ostr = ostr.SubString(1,30); nstr = nstr.SubString(1,30); ostr = CharReplace(ostr, 0x09, ' '); nstr = CharReplace(nstr, 0x09, ' '); ostr = CharReplace(ostr, 0x10, ' '); nstr = CharReplace(nstr, 0x10, ' '); ostr = CharReplace(ostr, 0x12, ' '); nstr = CharReplace(nstr, 0x12, ' '); act_info += ";" + trec->Items[i]->Name + "=<" + nstr + ">old=<" + ostr + ">"; } } // FAct_Update wrec->FullClear(); trec->FullClear(); if (DM->ExecModifySql(sqltext)) { bool bs = false; // Blob is Saved -> FullRefresh else RefreshRecord try { bs = QryMain_BlobSave(FQryMain_PK); } catch (Exception &xcp) { OEMessage_Show(FBaseTable_Name + ": Save blob fields\n" + xcp.Message); } if (FAct_Update) { if (bs) act_info += ";Blob_updated"; DM->RegAction(this, act_info); } BaseTableIsModified = true; if (bs || QryMain->RowId().IsEmpty() || FBaseTable_Alias.IsEmpty()) QryMain_Refresh (0); else QryMain->RefreshRecord(); // *AVC 30.05.2003 if (QryMain && QryMain->Active && !QryMain->IsEmpty()) { WORD k = Grd_Main->LastKeyDown; if (k == VK_DOWN) QryMain->Next (); else if (k == VK_UP ) QryMain->Prior(); else ; } Grd_Main->LastKeyDown = 0; } } //--------------------------------------------------------------------------- void __fastcall TF_UniEdit::QryMain_PostInsert (void) // Save Insert { // Новые данные зачитаны в FMainRecord функцией (QryMainBeforePost) Grd_Main->SetFocus(); // Рассчет списка полей для Insert на базе анализа списка полей базовой таблици if (FBaseTable_FieldsList.IsEmpty()) PrepareBaseTable_FieldsList(); if (FBaseTable_FieldsList.IsEmpty()) FBaseTable_FieldsList = "Null"; if (FBaseTable_FieldsList == "Null") { OEMessage_Show("При добавлении записи не удалось получить список полей базовой таблици."); return; } TAxRecord *trec = FTmpRecord; trec->FullClear(); trec->UpdAdd(FMainRecord, FBaseTable_FieldsList); trec->SetAllReadOnly (false, FQryMain_PKName); trec->SetAllNeedInSQL(false, "Created_On, Ctreated_By, Changed_On, Changed_By"); if (FQryMain_PK != 0) { TAxField *fax = trec->ByName(FQryMain_PKName); if (fax) { fax->ReadOnly = false; fax->AsInteger = FQryMain_PK; } } // RecordInfo(trec); // edit_marker 7 AnsiString sqltext = AnsiString("") + "Insert Into " + FBaseTable + " " + trec->InsertBody() + " \nReturning " + FQryMain_PKName + " Into :retPkID"; trec->UpdAdd("retPkID", int(0)); // ShowMessage (sqltext); if (DM->ExecModifySql(sqltext, trec, true)) { try { QryMain_BlobSave(trec->ByName("retPkID")->AsInteger); } catch (Exception &xcp) { OEMessage_Show(FBaseTable_Name + ": Save blob fields\n" + xcp.Message); } int ncode = trec->ByName("retPkID")->AsInteger; AnsiString name; name = AnsiString("Ins ") + FBaseTable_Name + ": " + "ID=" + AnsiString(ncode); if (FAct_Insert) DM->RegAction(this, name); BaseTableIsModified = true; QryMain_Refresh (ncode); // *AVC 30.05.2003 if (QryMain && QryMain->Active && !QryMain->IsEmpty()) { WORD k = Grd_Main->LastKeyDown; if (k == VK_DOWN) QryMain->Next (); else if (k == VK_UP ) QryMain->Prior(); else ; } Grd_Main->LastKeyDown = 0; } trec->FullClear(); } //--------------------------------------------------------------------------- bool __fastcall TF_UniEdit::QryMain_BlobSave (int pkID) // Сохранить blob поля { // Новые данные зачитаны в FMainRecord функцией (QryMainBeforePost) // У FQM_BlobFields NeedInSQL = TBlobField->Modified (true если поле изменилось) if (!FQM_BlobFields || FQM_BlobFields->Count == 0 || pkID == 0) return false; TAxField *fax; TField *fld; TBlobField *blob; AnsiString text = ""; for (int i=0; i < FQM_BlobFields->Count; i++) { fax = FQM_BlobFields->Items[i]; if (!fax->NeedInSQL) continue; fld = QryMain->FindField(fax->Name); if (!fld) continue; blob = dynamic_cast(fld); if (!blob) continue; text += " ," + fax->Name + "\n"; } if (text.IsEmpty()) return false; text = AnsiString("") + "Select\n ROWID \n" + text + " From " + FBaseTable + " Where " + FQryMain_PKName + " = " + AnsiString(pkID) + ""; // ShowMessage(text); TOracleDataSet *qry = QryWork; if (qry->Active) qry->Active = false; qry->ReadOnly = false; qry->DeleteVariables(); if (!DM->ExecROSql(qry, text)) return false; if (qry->IsEmpty()) { qry->Active = false; qry->ReadOnly = true; qry->DeleteVariables(); return false; } try { qry->First(); qry->Edit(); // edit_marker 8 for (int i=0; i < FQM_BlobFields->Count; i++) { fax = FMainRecord->ByName(FQM_BlobFields->Items[i]->Name); fld = qry->FindField (FQM_BlobFields->Items[i]->Name); if (fax && fld) fld->Value = fax->Value; } qry->Post(); if (qry->Session->InTransaction()) qry->Session->Commit(); } // try catch (Exception &xcp) { if (qry->Session->InTransaction()) qry->Session->Rollback(); if (qry->Active) qry->Active = false; qry->ReadOnly = true; qry->DeleteVariables(); throw; } if (qry->Active) qry->Active = false; qry->ReadOnly = true; qry->DeleteVariables(); // *AVC 23.05.2003 // При редактировании AppMem при частом изменении скрипта Swop не обновляется // Будем стирать файл swop'a if (FBaseTable_Name.UpperCase() == "APPMEM") { text = DirAdds(DM->Swp_Files_Path) + ClpStrZero(pkID, 6, 0) + ".apm"; if (FileExists(text)) DeleteFile(text); } return true; } //---------------------------------------------------------------------------