You've already forked lazarus-ccr
1178 lines
31 KiB
ObjectPascal
1178 lines
31 KiB
ObjectPascal
![]() |
{*********************************************************}
|
||
|
{* Classes for server, database, and table lists *}
|
||
|
{*********************************************************}
|
||
|
|
||
|
(* ***** BEGIN LICENSE BLOCK *****
|
||
|
* Version: MPL 1.1
|
||
|
*
|
||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||
|
* the License. You may obtain a copy of the License at
|
||
|
* http://www.mozilla.org/MPL/
|
||
|
*
|
||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* License.
|
||
|
*
|
||
|
* The Original Code is TurboPower FlashFiler
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is
|
||
|
* TurboPower Software
|
||
|
*
|
||
|
* Portions created by the Initial Developer are Copyright (C) 1996-2002
|
||
|
* the Initial Developer. All Rights Reserved.
|
||
|
*
|
||
|
* Contributor(s):
|
||
|
*
|
||
|
* ***** END LICENSE BLOCK ***** *)
|
||
|
|
||
|
{$I ffdefine.inc}
|
||
|
|
||
|
unit uentity;
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses
|
||
|
Classes,
|
||
|
Controls,
|
||
|
Consts,
|
||
|
DB,
|
||
|
Dialogs,
|
||
|
Forms,
|
||
|
SysUtils,
|
||
|
Windows,
|
||
|
ffclbase,
|
||
|
ffllbase,
|
||
|
fflldict,
|
||
|
ffllprot,
|
||
|
ffclreng,
|
||
|
ffdb,
|
||
|
fflllgcy,
|
||
|
fflllog,
|
||
|
fflogdlg,
|
||
|
ffsrbde;
|
||
|
|
||
|
type
|
||
|
TffexpSession = class(TffSession)
|
||
|
protected
|
||
|
procedure FFELogin(aSource : TObject;
|
||
|
var aUserName : TffName;
|
||
|
var aPassword : TffName;
|
||
|
var aResult : Boolean);
|
||
|
public
|
||
|
ffePassword : string;
|
||
|
ffeUserName : string;
|
||
|
public
|
||
|
constructor Create(AOwner : TComponent); override;
|
||
|
end;
|
||
|
TffexpDatabase = class(TffDatabase);
|
||
|
TffexpTable = class(TffTable);
|
||
|
|
||
|
type
|
||
|
TffeEntityType = (etServer, etDatabase, etTable);
|
||
|
TffeServerList = class;
|
||
|
TffeDatabaseList = class;
|
||
|
TffeDatabaseItem = class;
|
||
|
TffeTableList = class;
|
||
|
TffeTableItem = class;
|
||
|
|
||
|
TffeEntityItem = class(TffListItem)
|
||
|
protected { private}
|
||
|
FEntityType: TffeEntityType;
|
||
|
FEntityName: TffNetAddress;
|
||
|
FEntitySerialKey: DWORD;
|
||
|
public
|
||
|
constructor Create(aEntityType: TffeEntityType; aEntityName: TffShStr);
|
||
|
|
||
|
function Compare(aKey : Pointer): Integer; override;
|
||
|
{-compare Self's key to aKey: return <0 if aKey < Self's, 0 if
|
||
|
equal, >0 otherwise}
|
||
|
|
||
|
function Key: Pointer; override;
|
||
|
{-return a pointer to this item's key: it'll be a pointer to a
|
||
|
shortstring}
|
||
|
|
||
|
property EntityType: TffeEntityType
|
||
|
read FEntityType;
|
||
|
|
||
|
property EntityName: TffNetAddress
|
||
|
read FEntityName;
|
||
|
|
||
|
property EntitySerialKey: DWORD
|
||
|
read FEntitySerialKey;
|
||
|
end;
|
||
|
|
||
|
TffeEntityList = class(TffList)
|
||
|
protected
|
||
|
function GetItem(aIndex: LongInt): TffeEntityItem;
|
||
|
public
|
||
|
function IndexOfName(const aName: TffShStr): LongInt;
|
||
|
{-return the index of the entry whose name is given}
|
||
|
|
||
|
function IndexOfSerialKey(aSerialKey: DWORD): LongInt;
|
||
|
{-return the list index for a given entity identified by its
|
||
|
serial key (the outline control keeps track of entities
|
||
|
by the serial key) }
|
||
|
|
||
|
property Items[aIndex: LongInt]: TffeEntityItem
|
||
|
read GetItem;
|
||
|
end;
|
||
|
|
||
|
TffeServerNotifyEvent = procedure(aServerIndex: LongInt) of object;
|
||
|
|
||
|
TffeServerItem = class(TffeEntityItem)
|
||
|
protected
|
||
|
FClient : TffClient;
|
||
|
FDatabaseList: TffeDatabaseList;
|
||
|
FProtocol : TffProtocolType;
|
||
|
FServerEngine : TffRemoteServerEngine;
|
||
|
FSession : TffexpSession;
|
||
|
FTransport : TffLegacyTransport;
|
||
|
|
||
|
procedure siCheckAttached;
|
||
|
function siGetDatabaseCount : longInt;
|
||
|
function siGetDatabase(const anIndex : longInt) : TffeDatabaseItem;
|
||
|
|
||
|
public
|
||
|
ServerID: LongInt;
|
||
|
Attached: Boolean;
|
||
|
|
||
|
constructor Create(aServerName: TffNetAddress;
|
||
|
aProtocol : TffProtocolType);
|
||
|
destructor Destroy; override;
|
||
|
procedure AddAlias(aAlias : TffName;
|
||
|
aPath : TffPath;
|
||
|
aCheckSpace : Boolean); {!!.11}
|
||
|
function AddDatabase(aAlias : TffName) : TffeDatabaseItem;
|
||
|
function Attach(aLog : TffBaseLog): TffResult;
|
||
|
procedure Detach;
|
||
|
procedure DropDatabase(aDatabaseName : TffName);
|
||
|
procedure GetAliases(aList : TStrings);
|
||
|
function GetAutoInc(aTable : TffTable) : TffWord32;
|
||
|
procedure LoadDatabases;
|
||
|
|
||
|
property DatabaseCount : longInt read siGetDatabaseCount;
|
||
|
property Databases[const anIndex : longInt] : TffeDatabaseItem
|
||
|
read siGetDatabase;
|
||
|
property ServerName: TffNetAddress read FEntityName;
|
||
|
property Session : TffexpSession read FSession;
|
||
|
property Protocol : TffProtocolType read FProtocol; {!!.10}
|
||
|
property Client : TffClient read FClient; {!!.11}
|
||
|
end;
|
||
|
|
||
|
TffeServerList = class(TffeEntityList)
|
||
|
protected {private}
|
||
|
FClient : TffClient;
|
||
|
FOnAttach: TffeServerNotifyEvent;
|
||
|
FOnDetach: TffeServerNotifyEvent;
|
||
|
FServerEngine : TffRemoteServerEngine;
|
||
|
FTransport : TffLegacyTransport;
|
||
|
|
||
|
function GetItem(aIndex: LongInt): TffeServerItem;
|
||
|
public
|
||
|
constructor Create(aLog : TffBaseLog);
|
||
|
destructor Destroy; override;
|
||
|
procedure DetachAll;
|
||
|
function Insert(aItem: TffeServerItem): Boolean;
|
||
|
procedure Load;
|
||
|
procedure LoadRegisteredServers;
|
||
|
|
||
|
property Items[aIndex: LongInt]: TffeServerItem
|
||
|
read GetItem;
|
||
|
|
||
|
property OnAttach: TffeServerNotifyEvent
|
||
|
read FOnAttach write FOnAttach;
|
||
|
property OnDetach: TffeServerNotifyEvent
|
||
|
read FOnDetach write FOnDetach;
|
||
|
end;
|
||
|
|
||
|
TffeDatabaseItem = class(TffeEntityItem)
|
||
|
protected
|
||
|
FDatabase : TffexpDatabase;
|
||
|
FServer : TffeServerItem;
|
||
|
FTableList : TffeTableList;
|
||
|
diParentList: TffeDatabaseList;
|
||
|
|
||
|
function diGetIsOpen: Boolean;
|
||
|
function diGetServer: TffeServerItem;
|
||
|
function diGetTable(const anIndex : longInt) : TffeTableItem;
|
||
|
function diGetTableCount : longInt;
|
||
|
|
||
|
public
|
||
|
DatabaseID: LongInt; { FF internal DB Identifier }
|
||
|
constructor Create(aServer : TffeServerItem; aAliasName: TffName);
|
||
|
destructor Destroy; override;
|
||
|
procedure Close;
|
||
|
function AddTable(const aTableName : TffTableName) : longInt;
|
||
|
procedure CreateTable(const aTableName: TffTableName; aDict: TffDataDictionary);
|
||
|
procedure DropTable(const anIndex : longInt);
|
||
|
{ Drop the specified table from the list of tables. }
|
||
|
procedure GetTableNames(Tables: TStrings);
|
||
|
function IndexOf(aTable : TffeTableItem) : longInt;
|
||
|
procedure LoadTables;
|
||
|
procedure Open;
|
||
|
procedure Rename(aNewName: TffNetAddress);
|
||
|
property Database : TffexpDatabase read FDatabase;
|
||
|
property DatabaseName: TffNetAddress read FEntityName;
|
||
|
property IsOpen: Boolean read diGetIsOpen;
|
||
|
property Server: TffeServerItem read diGetServer;
|
||
|
property TableCount : longInt read diGetTableCount;
|
||
|
property Tables[const anIndex : longInt] : TffeTableItem
|
||
|
read diGetTable;
|
||
|
end;
|
||
|
|
||
|
TffeDatabaseList = class(TffeEntityList)
|
||
|
protected
|
||
|
FServer : TffeServerItem;
|
||
|
|
||
|
function GetItem(aIndex: LongInt): TffeDatabaseItem;
|
||
|
public
|
||
|
constructor Create(aServer : TffeServerItem);
|
||
|
destructor Destroy; override;
|
||
|
function Add(const aDatabaseName: TffName): TffeDatabaseItem;
|
||
|
procedure DropDatabase(aIndex: LongInt);
|
||
|
function Insert(aItem: TffeDatabaseItem): Boolean;
|
||
|
procedure Load;
|
||
|
{ Load the aliases for the server. }
|
||
|
|
||
|
property Items[aIndex: LongInt]: TffeDatabaseItem
|
||
|
read GetItem;
|
||
|
end;
|
||
|
|
||
|
TffeTableItem = class(TffeEntityItem)
|
||
|
protected {private}
|
||
|
FParent : TffeDatabaseItem;
|
||
|
protected
|
||
|
tiParentList: TffeTableList;
|
||
|
procedure AfterOpenEvent(aDataset: TDataset);
|
||
|
function GetDatabase: TffeDatabaseItem;
|
||
|
function GetDictionary: TffDataDictionary;
|
||
|
function GetRebuilding: Boolean;
|
||
|
function GetRecordCount: TffWord32;
|
||
|
function GetServer: TffeServerItem;
|
||
|
public
|
||
|
Table: TffexpTable;
|
||
|
DatabaseIndex: LongInt;
|
||
|
CursorID: LongInt;
|
||
|
TaskID: LongInt;
|
||
|
constructor Create(aDatabase : TffeDatabaseItem; aTableName: TffName);
|
||
|
destructor Destroy; override;
|
||
|
|
||
|
procedure CheckRebuildStatus(var aCompleted: Boolean;
|
||
|
var aStatus: TffRebuildStatus);
|
||
|
function GetAutoInc : TffWord32;
|
||
|
procedure Pack;
|
||
|
procedure Reindex(aIndexNum: Integer);
|
||
|
procedure Rename(aNewTableName: TffName);
|
||
|
procedure Restructure(aDictionary: TffDataDictionary; aFieldMap: TStrings);
|
||
|
procedure SetAutoIncSeed(aValue : LongInt);
|
||
|
procedure Truncate;
|
||
|
procedure CopyRecords(aSrcTable : TffDataSet; aCopyBLOBs : Boolean); {!!.10}
|
||
|
|
||
|
property Database: TffeDatabaseItem
|
||
|
read GetDatabase;
|
||
|
property Dictionary: TffDataDictionary
|
||
|
read GetDictionary;
|
||
|
property Rebuilding: Boolean
|
||
|
read GetRebuilding;
|
||
|
property RecordCount: TffWord32
|
||
|
read GetRecordCount;
|
||
|
property Server: TffeServerItem
|
||
|
read GetServer;
|
||
|
property TableName: TffNetAddress
|
||
|
read FEntityName;
|
||
|
end;
|
||
|
|
||
|
TffeTableList = class(TffeEntityList)
|
||
|
protected
|
||
|
FDatabase : TffeDatabaseItem;
|
||
|
function GetItem(aIndex: LongInt): TffeTableItem;
|
||
|
public
|
||
|
constructor Create(aDatabase : TffeDatabaseItem);
|
||
|
destructor Destroy; override;
|
||
|
function Add(const aTableName: TffName): longInt;
|
||
|
procedure DropTable(aIndex: LongInt);
|
||
|
function Insert(aItem: TffeTableItem): Boolean;
|
||
|
procedure Load;
|
||
|
|
||
|
property Items[aIndex: LongInt]: TffeTableItem
|
||
|
read GetItem;
|
||
|
end;
|
||
|
|
||
|
const
|
||
|
ffcConnectTimeout : longInt = 2000;
|
||
|
{-Number of milliseconds we will wait for servers to respond to our
|
||
|
broadcast. }
|
||
|
|
||
|
implementation
|
||
|
|
||
|
uses
|
||
|
ffclcfg,
|
||
|
ffdbbase,
|
||
|
ffllcomm,
|
||
|
ffllcomp,
|
||
|
fflleng,
|
||
|
ubase,
|
||
|
uconsts,
|
||
|
{$IFDEF DCC6ORLATER} {!!.03}
|
||
|
RTLConsts, {!!.03}
|
||
|
{$ENDIF} {!!.03}
|
||
|
uconfig;
|
||
|
|
||
|
const
|
||
|
ffcLogName = 'ffe.log';
|
||
|
ffcDatabaseClosed = 'Cannot perform this operation on a closed database';
|
||
|
|
||
|
var
|
||
|
NextEntitySerialKey: DWORD;
|
||
|
|
||
|
{=====TffeEntityItem methods=====}
|
||
|
|
||
|
constructor TffeEntityItem.Create(aEntityType: TffeEntityType; aEntityName: TffShStr);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
FEntityType := aEntityType;
|
||
|
FEntityName := aEntityName;
|
||
|
FEntitySerialKey := NextEntitySerialKey;
|
||
|
Inc(NextEntitySerialKey);
|
||
|
end;
|
||
|
|
||
|
function TffeEntityItem.Compare(aKey: Pointer): Integer;
|
||
|
begin
|
||
|
Result := FFCmpShStr(PffShStr(aKey)^, EntityName, 255);
|
||
|
end;
|
||
|
|
||
|
function TffeEntityItem.Key: Pointer;
|
||
|
begin
|
||
|
Result := @FEntityName;
|
||
|
end;
|
||
|
|
||
|
{=====TffeEntityList methods=====}
|
||
|
|
||
|
function TffeEntityList.GetItem(aIndex: LongInt): TffeEntityItem;
|
||
|
begin
|
||
|
if (aIndex < 0) or (aIndex >= Count) then
|
||
|
raise EListError.Create(SListIndexError);
|
||
|
Result := TffeEntityItem(inherited Items[aIndex]);
|
||
|
end;
|
||
|
|
||
|
function TffeEntityList.IndexOfName(const aName: TffShStr): LongInt;
|
||
|
begin
|
||
|
for Result := 0 to Count - 1 do
|
||
|
if Items[Result].EntityName = aName then Exit;
|
||
|
Result := -1;
|
||
|
end;
|
||
|
|
||
|
function TffeEntityList.IndexOfSerialKey(aSerialKey: DWORD): LongInt;
|
||
|
begin
|
||
|
for Result := 0 to Count - 1 do
|
||
|
if Items[Result].EntitySerialKey = aSerialKey then Exit;
|
||
|
Result := -1;
|
||
|
end;
|
||
|
|
||
|
{===TffeServerItem===================================================}
|
||
|
constructor TffeServerItem.Create(aServerName: TffNetAddress;
|
||
|
aProtocol : TffProtocolType);
|
||
|
begin
|
||
|
inherited Create(etServer, FFShStrTrim(aServerName));
|
||
|
FDatabaseList := TffeDatabaseList.Create(Self);
|
||
|
FProtocol := aProtocol;
|
||
|
Attached := False;
|
||
|
end;
|
||
|
{--------}
|
||
|
destructor TffeServerItem.Destroy;
|
||
|
begin
|
||
|
Detach;
|
||
|
FDatabaseList.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeServerItem.AddAlias(aAlias : TffName;
|
||
|
aPath : TffPath;
|
||
|
aCheckSpace : Boolean); {!!.11}
|
||
|
begin
|
||
|
FSession.AddAlias(aAlias, aPath, aCheckSpace); {!!.11}
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeServerItem.AddDatabase(aAlias : TffName) : TffeDatabaseItem;
|
||
|
begin
|
||
|
Result := FDatabaseList.Add(aAlias);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeServerItem.Attach(aLog : TffBaseLog): TffResult;
|
||
|
var
|
||
|
OldCursor: TCursor;
|
||
|
begin
|
||
|
Result := DBIERR_NONE;
|
||
|
|
||
|
{ If we're already attached, then we don't need to do anything }
|
||
|
if Attached then Exit;
|
||
|
|
||
|
OldCursor := Screen.Cursor;
|
||
|
Screen.Cursor := crHourglass;
|
||
|
try
|
||
|
|
||
|
if not assigned(FTransport) then
|
||
|
FTransport := TffLegacyTransport.Create(nil);
|
||
|
with FTransport do begin
|
||
|
Mode := fftmSend;
|
||
|
Enabled := True;
|
||
|
Protocol := FProtocol;
|
||
|
EventLog := aLog;
|
||
|
EventLogEnabled := True;
|
||
|
EventLogOptions := [fftpLogErrors];
|
||
|
ServerName := FEntityName;
|
||
|
end;
|
||
|
|
||
|
if not assigned(FServerEngine) then
|
||
|
FServerEngine := TffRemoteServerEngine.Create(nil);
|
||
|
with FServerEngine do begin
|
||
|
Transport := FTransport;
|
||
|
end;
|
||
|
|
||
|
if not assigned(FClient) then
|
||
|
FClient := TffClient.Create(nil);
|
||
|
with FClient do begin
|
||
|
TimeOut := Config.DefaultTimeout; {!!.11}
|
||
|
ServerEngine := FServerEngine;
|
||
|
AutoClientName := True;
|
||
|
Active := True;
|
||
|
end;
|
||
|
|
||
|
if not assigned(FSession) then
|
||
|
FSession := TffexpSession.Create(nil);
|
||
|
with FSession do begin
|
||
|
ClientName := FClient.ClientName;
|
||
|
AutoSessionName := True;
|
||
|
Active := True;
|
||
|
end;
|
||
|
|
||
|
Attached := FSession.Active;
|
||
|
if Attached then begin
|
||
|
{ Automatically load up all the databases for this server }
|
||
|
if not assigned(FDatabaseList) then
|
||
|
FDatabaseList := TffeDatabaseList.Create(Self);
|
||
|
FDatabaseList.Load;
|
||
|
|
||
|
{ Run the event-handler if any }
|
||
|
with ServerList do
|
||
|
if Assigned(FOnAttach) then
|
||
|
FOnAttach(Index(FEntityName));
|
||
|
end;
|
||
|
finally;
|
||
|
Screen.Cursor := OldCursor;
|
||
|
end;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeServerItem.Detach;
|
||
|
var
|
||
|
S: TffNetAddress;
|
||
|
begin
|
||
|
|
||
|
if assigned(FDatabaseList) then begin
|
||
|
FDatabaseList.Free;
|
||
|
FDatabaseList := nil;
|
||
|
end;
|
||
|
|
||
|
if assigned(FSession) then begin
|
||
|
FSession.Active := False;
|
||
|
FSession.Free;
|
||
|
FSession := nil;
|
||
|
end;
|
||
|
|
||
|
if assigned(FClient) then begin
|
||
|
FClient.Active := False;
|
||
|
FClient.Free;
|
||
|
FClient := nil;
|
||
|
end;
|
||
|
|
||
|
if assigned(FTransport) then begin
|
||
|
FTransport.State := ffesInactive;
|
||
|
FTransport.Free;
|
||
|
FTransport := nil;
|
||
|
end;
|
||
|
|
||
|
if assigned(FServerEngine) then begin
|
||
|
FServerEngine.Free;
|
||
|
FServerEngine := nil;
|
||
|
end;
|
||
|
|
||
|
Attached := False;
|
||
|
|
||
|
S := ServerName;
|
||
|
with ServerList do
|
||
|
if Assigned(FOnDetach) then
|
||
|
FOnDetach(Index(S));
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeServerItem.DropDatabase(aDatabaseName : TffName);
|
||
|
begin
|
||
|
siCheckAttached;
|
||
|
FDatabaseList.DropDatabase(FDatabaseList.IndexOfName(aDatabaseName));
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeServerItem.GetAliases(aList : TStrings);
|
||
|
begin
|
||
|
siCheckAttached;
|
||
|
FSession.GetAliasNames(aList);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeServerItem.GetAutoInc(aTable : TffTable) : TffWord32;
|
||
|
begin
|
||
|
Result := 1;
|
||
|
FServerEngine.TableGetAutoInc(aTable.CursorID, Result);
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeServerItem.LoadDatabases;
|
||
|
begin
|
||
|
siCheckAttached;
|
||
|
FDatabaseList.Load;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeServerItem.siCheckAttached;
|
||
|
begin
|
||
|
if not Attached then
|
||
|
Attach(nil);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeServerItem.siGetDatabaseCount : longInt;
|
||
|
begin
|
||
|
Result := FDatabaseList.Count;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeServerItem.siGetDatabase(const anIndex : Longint)
|
||
|
: TffeDatabaseItem;
|
||
|
begin
|
||
|
Result := TffeDatabaseItem(FDatabaseList[anIndex]);
|
||
|
end;
|
||
|
{====================================================================}
|
||
|
|
||
|
{===TffeServerList===================================================}
|
||
|
constructor TffeServerList.Create(aLog : TffBaseLog);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
Sorted := True;
|
||
|
|
||
|
{ The transport will be left inactive. Its sole purpose is to
|
||
|
broadcast for servers using the protocol identified in the registry. }
|
||
|
FTransport := TffLegacyTransport.Create(nil);
|
||
|
with FTransport do begin
|
||
|
Mode := fftmSend;
|
||
|
Enabled := True;
|
||
|
Protocol := ptRegistry;
|
||
|
EventLog := aLog;
|
||
|
EventLogEnabled := True;
|
||
|
EventLogOptions := [fftpLogErrors];
|
||
|
Name := 'ffeTransport';
|
||
|
end;
|
||
|
|
||
|
FServerEngine := TffRemoteServerEngine.Create(nil);
|
||
|
with FServerEngine do begin
|
||
|
Transport := FTransport;
|
||
|
Name := 'ffeServerEngine';
|
||
|
end;
|
||
|
|
||
|
FClient := TffClient.Create(nil);
|
||
|
with FClient do begin
|
||
|
ServerEngine := FServerEngine;
|
||
|
Name := 'ffeClient';
|
||
|
ClientName := Name;
|
||
|
Timeout := ffcConnectTimeout;
|
||
|
Active := True;
|
||
|
end;
|
||
|
|
||
|
end;
|
||
|
{--------}
|
||
|
destructor TffeServerList.Destroy;
|
||
|
begin
|
||
|
Empty;
|
||
|
FClient.Active := False;
|
||
|
FClient.Free;
|
||
|
FServerEngine.Free;
|
||
|
FTransport.State := ffesInactive;
|
||
|
FTransport.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeServerList.DetachAll;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
for I := 0 to Count - 1 do
|
||
|
with Items[I] do
|
||
|
if Attached then Detach;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeServerList.Insert(aItem: TffeServerItem): Boolean;
|
||
|
begin
|
||
|
Result := inherited Insert(aItem);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeServerList.GetItem(aIndex: LongInt): TffeServerItem;
|
||
|
begin
|
||
|
Result := TffeServerItem(inherited Items[aIndex]);
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeServerList.Load;
|
||
|
var
|
||
|
Servers: TStringList;
|
||
|
I: Integer;
|
||
|
tryProt: TffProtocolType; {!!.10}
|
||
|
|
||
|
function ServerRegistered(const ServerName : string) : Boolean; {begin !!.06}
|
||
|
var
|
||
|
Idx : Integer;
|
||
|
begin
|
||
|
Result := False;
|
||
|
with Config do
|
||
|
for Idx := 0 to Pred(RegisteredServers.Count) do
|
||
|
if FFAnsiCompareText(ServerName, RegisteredServers[Idx]) = 0 then begin {!!.10}
|
||
|
Result := True;
|
||
|
Exit;
|
||
|
end;
|
||
|
end; {end !!.06}
|
||
|
|
||
|
begin
|
||
|
Empty;
|
||
|
|
||
|
// if not (Config.Protocol = TffSingleUserProtocol) then {!!.06}
|
||
|
LoadRegisteredServers;
|
||
|
|
||
|
{Begin !!.07}
|
||
|
{ added loop to try all protocols. we no longer let the user
|
||
|
select protocol, but instead list all servers on all protocols. }
|
||
|
{ Broadcast for currently active servers }
|
||
|
Servers := TStringList.Create;
|
||
|
try
|
||
|
for tryProt := ptSingleUser to ptIPXSPX do begin
|
||
|
try
|
||
|
FTransport.Enabled := False;
|
||
|
FTransport.Protocol := tryProt;
|
||
|
FClient.GetServerNames(Servers);
|
||
|
for I := 0 to Servers.Count - 1 do
|
||
|
if not ServerRegistered(Servers[I]) then {!!.06}
|
||
|
Insert(TffeServerItem.Create(Servers[I], tryProt));
|
||
|
except
|
||
|
{ swallow all errors. assume that the particular protocol failed. }
|
||
|
end;
|
||
|
end;
|
||
|
{End !!.07}
|
||
|
finally
|
||
|
Servers.Free;
|
||
|
end;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeServerList.LoadRegisteredServers;
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
with Config.RegisteredServers do
|
||
|
for I := 0 to Count - 1 do
|
||
|
Self.Insert(TffeServerItem.Create(Strings[I], ptTCPIP)); {!!.10} {changed protocol type}
|
||
|
end;
|
||
|
{=====================================================================}
|
||
|
|
||
|
{== TffeDatabaseItem =================================================}
|
||
|
constructor TffeDatabaseItem.Create(aServer : TffeServerItem;
|
||
|
aAliasName : TffName);
|
||
|
begin
|
||
|
inherited Create(etDatabase, aAliasName);
|
||
|
FServer := aServer;
|
||
|
DatabaseID := -1;
|
||
|
diParentList := nil;
|
||
|
FDatabase := TffexpDatabase.Create(nil);
|
||
|
FTableList := TffeTableList.Create(Self);
|
||
|
with FDatabase do begin
|
||
|
DatabaseName := 'exp' + aAliasName;
|
||
|
SessionName := aServer.Session.SessionName;
|
||
|
AliasName := aAliasName;
|
||
|
end;
|
||
|
end;
|
||
|
{--------}
|
||
|
destructor TffeDatabaseItem.Destroy;
|
||
|
begin
|
||
|
if IsOpen then Close;
|
||
|
FTableList.Free;
|
||
|
FDatabase.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeDatabaseItem.Close;
|
||
|
begin
|
||
|
FDatabase.Connected := False;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeDatabaseItem.AddTable(const aTableName : TffTableName)
|
||
|
: Longint;
|
||
|
begin
|
||
|
Result := FTableList.Add(aTableName);
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeDatabaseItem.CreateTable(const aTableName : TffTableName;
|
||
|
aDict : TffDataDictionary);
|
||
|
begin
|
||
|
if not IsOpen then
|
||
|
Open;
|
||
|
|
||
|
Check(FDatabase.CreateTable(False, aTableName, aDict));
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeDatabaseItem.DropTable(const anIndex : longInt);
|
||
|
begin
|
||
|
FTableList.DropTable(anIndex);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeDatabaseItem.diGetIsOpen: Boolean;
|
||
|
begin
|
||
|
Result := FDatabase.Connected;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeDatabaseItem.diGetServer: TffeServerItem;
|
||
|
begin
|
||
|
Result := FServer;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeDatabaseItem.diGetTable(const anIndex : longInt) : TffeTableItem;
|
||
|
begin
|
||
|
Result := TffeTableItem(FTableList[anIndex]);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeDatabaseItem.diGetTableCount : longInt;
|
||
|
begin
|
||
|
Result := FTableList.Count;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeDatabaseItem.GetTableNames(Tables: TStrings);
|
||
|
begin
|
||
|
if Tables is TStringList then
|
||
|
TStringList(Tables).Sorted := True;
|
||
|
FDatabase.GetTableNames(Tables);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeDatabaseItem.IndexOf(aTable : TffeTableItem) : longInt;
|
||
|
begin
|
||
|
Result := FTableList.IndexOfName(aTable.TableName);
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeDatabaseItem.LoadTables;
|
||
|
{ Find all the tables in the database and add to the table list. }
|
||
|
var
|
||
|
Tables: TStringList;
|
||
|
I: Integer;
|
||
|
begin
|
||
|
Tables := TStringList.Create;
|
||
|
try
|
||
|
FTableList.Empty;
|
||
|
// try
|
||
|
FDatabase.GetTableNames(Tables);
|
||
|
for I := 0 to Tables.Count - 1 do
|
||
|
FTableList.Add(Tables[I]);
|
||
|
{ except
|
||
|
on EffDatabaseError do
|
||
|
{do nothing}
|
||
|
{ else
|
||
|
raise;
|
||
|
end;}
|
||
|
finally
|
||
|
Tables.Free;
|
||
|
end;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeDatabaseItem.Open;
|
||
|
begin
|
||
|
FDatabase.Connected := True;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeDatabaseItem.Rename(aNewName: TffNetAddress);
|
||
|
begin
|
||
|
FDatabase.Close;
|
||
|
Check(FServer.Session.ModifyAlias(FEntityName, aNewName, '', False)); {!!.11}
|
||
|
FEntityName := aNewName;
|
||
|
end;
|
||
|
{=====================================================================}
|
||
|
|
||
|
{== TffeDatabaseList =================================================}
|
||
|
constructor TffeDatabaseList.Create(aServer : TffeServerItem);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
FServer := aServer;
|
||
|
Sorted := False;
|
||
|
end;
|
||
|
{--------}
|
||
|
destructor TffeDatabaseList.Destroy;
|
||
|
begin
|
||
|
{ Close all databases. }
|
||
|
Empty;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeDatabaseList.Add(const aDatabaseName : TffName)
|
||
|
: TffeDatabaseItem;
|
||
|
begin
|
||
|
Result := TffeDatabaseItem.Create(FServer, aDatabaseName);
|
||
|
Insert(Result);
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeDatabaseList.DropDatabase(aIndex: LongInt);
|
||
|
begin
|
||
|
with Items[aIndex] do begin
|
||
|
FDatabase.Connected := False;
|
||
|
FServer.Session.DeleteAlias(DatabaseName);
|
||
|
end;
|
||
|
DeleteAt(aIndex);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeDatabaseList.GetItem(aIndex: LongInt): TffeDatabaseItem;
|
||
|
begin
|
||
|
Result := TffeDatabaseItem(inherited Items[aIndex]);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeDatabaseList.Insert(aItem: TffeDatabaseItem): Boolean;
|
||
|
begin
|
||
|
aItem.diParentList := Self;
|
||
|
Result := inherited Insert(AItem);
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeDatabaseList.Load;
|
||
|
var
|
||
|
Aliases : TStringList;
|
||
|
Index : longInt;
|
||
|
OldCursor: TCursor;
|
||
|
begin
|
||
|
OldCursor := Screen.Cursor;
|
||
|
Aliases := TStringList.Create;
|
||
|
Screen.Cursor := crHourglass;
|
||
|
try
|
||
|
Empty;
|
||
|
FServer.GetAliases(Aliases);
|
||
|
for Index := 0 to pred(Aliases.Count) do begin
|
||
|
Add(Aliases[Index]);
|
||
|
end;
|
||
|
finally
|
||
|
Aliases.Free;
|
||
|
Screen.Cursor := OldCursor;
|
||
|
end;
|
||
|
end;
|
||
|
{=====================================================================}
|
||
|
|
||
|
{== TffeTableItem ====================================================}
|
||
|
constructor TffeTableItem.Create(aDatabase : TffeDatabaseItem;
|
||
|
aTableName : TffName);
|
||
|
begin
|
||
|
inherited Create(etTable, aTableName);
|
||
|
FParent := aDatabase;
|
||
|
CursorID := -1;
|
||
|
TaskID := -1;
|
||
|
tiParentList := nil;
|
||
|
Table := TffexpTable.Create(nil);
|
||
|
with Table do begin
|
||
|
SessionName := aDatabase.Server.Session.SessionName;
|
||
|
DatabaseName := aDatabase.Database.DatabaseName;
|
||
|
TableName := aTableName;
|
||
|
ReadOnly := False;
|
||
|
AfterOpen := AfterOpenEvent;
|
||
|
end;
|
||
|
end;
|
||
|
{--------}
|
||
|
destructor TffeTableItem.Destroy;
|
||
|
begin
|
||
|
Table.Free;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableItem.CheckRebuildStatus(var aCompleted: Boolean;
|
||
|
var aStatus: TffRebuildStatus);
|
||
|
var
|
||
|
WasOpen : Boolean;
|
||
|
begin
|
||
|
WasOpen := Database.IsOpen;
|
||
|
if not Database.IsOpen then
|
||
|
Database.Open;
|
||
|
|
||
|
try
|
||
|
Check(FParent.Server.Session.GetTaskStatus(TaskID, aCompleted, aStatus));
|
||
|
if aCompleted then
|
||
|
TaskID := -1;
|
||
|
except
|
||
|
TaskID := -1;
|
||
|
end;
|
||
|
if not WasOpen then
|
||
|
Database.Close;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeTableItem.GetAutoInc : TffWord32;
|
||
|
var
|
||
|
WasOpen : Boolean;
|
||
|
begin
|
||
|
WasOpen := Table.Active;
|
||
|
if not Table.Active then
|
||
|
Table.Open;
|
||
|
|
||
|
Result := FParent.Server.GetAutoInc(Table);
|
||
|
|
||
|
if not WasOpen then
|
||
|
Table.Close;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableItem.AfterOpenEvent(aDataset: TDataset);
|
||
|
var
|
||
|
I: Integer;
|
||
|
begin
|
||
|
with aDataset do
|
||
|
for I := 0 to FieldCount - 1 do
|
||
|
case Fields[I].DataType of
|
||
|
ftString: TStringField(Fields[I]).Transliterate := False;
|
||
|
ftMemo: TMemoField(Fields[I]).Transliterate := False;
|
||
|
end;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeTableItem.GetDatabase: TffeDatabaseItem;
|
||
|
begin
|
||
|
Result := FParent;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeTableItem.GetDictionary: TffDataDictionary;
|
||
|
var
|
||
|
WasOpen : Boolean;
|
||
|
begin
|
||
|
WasOpen := Table.Active;
|
||
|
if not Table.Active then
|
||
|
Table.Open;
|
||
|
|
||
|
Result := Table.Dictionary;
|
||
|
|
||
|
if not WasOpen then
|
||
|
Table.Close;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeTableItem.GetRebuilding: Boolean;
|
||
|
begin
|
||
|
Result := TaskID <> -1;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeTableItem.GetRecordCount: TffWord32;
|
||
|
var {!!.06}
|
||
|
WasOpen : Boolean; {!!.06}
|
||
|
begin {!!.06}
|
||
|
WasOpen := Table.Active;
|
||
|
if not Table.Active then
|
||
|
Table.Open;
|
||
|
|
||
|
Result := Table.RecordCount;
|
||
|
|
||
|
if WasOpen then {!!.06}
|
||
|
Table.Close; {!!.06}
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeTableItem.GetServer: TffeServerItem;
|
||
|
begin
|
||
|
Result := FParent.Server;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableItem.Pack;
|
||
|
var
|
||
|
WasOpen : Boolean;
|
||
|
begin
|
||
|
WasOpen := Database.IsOpen;
|
||
|
if not Database.IsOpen then
|
||
|
Database.Open;
|
||
|
|
||
|
Check(Database.FDatabase.PackTable(Table.TableName, TaskID));
|
||
|
|
||
|
if not WasOpen then
|
||
|
Database.Close;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableItem.Reindex(aIndexNum: Integer);
|
||
|
var
|
||
|
WasOpen: Boolean;
|
||
|
begin
|
||
|
WasOpen := Database.IsOpen;
|
||
|
if not Database.IsOpen then
|
||
|
Database.Open;
|
||
|
|
||
|
if Table.Active then Table.Close;
|
||
|
Check(Database.FDatabase.ReindexTable(Table.TableName, aIndexNum, TaskID));
|
||
|
|
||
|
if not WasOpen then
|
||
|
Database.Close;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableItem.Rename(aNewTableName: TffName);
|
||
|
begin
|
||
|
with Table do begin
|
||
|
if Active then Close;
|
||
|
RenameTable(aNewTableName);
|
||
|
FEntityName := aNewTableName;
|
||
|
end;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableItem.Restructure(aDictionary: TffDataDictionary; aFieldMap: TStrings);
|
||
|
var
|
||
|
Result: TffResult;
|
||
|
WasOpen: Boolean;
|
||
|
begin
|
||
|
WasOpen := Database.IsOpen;
|
||
|
if not Database.IsOpen then
|
||
|
Database.Open;
|
||
|
|
||
|
Table.Close;
|
||
|
|
||
|
Result := Database.FDatabase.RestructureTable
|
||
|
(Tablename, aDictionary, aFieldMap, TaskID);
|
||
|
if Result = DBIERR_INVALIDRESTROP then
|
||
|
raise Exception.Create('Cannot preserve data if user-defined indexes have been added or changed')
|
||
|
else Check(Result);
|
||
|
|
||
|
if not WasOpen then
|
||
|
Database.Close;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableItem.SetAutoIncSeed(aValue: Integer);
|
||
|
var
|
||
|
WasOpen : Boolean;
|
||
|
begin
|
||
|
WasOpen := Table.Active;
|
||
|
if not Table.Active then
|
||
|
Table.Open;
|
||
|
|
||
|
Check(Table.SetTableAutoIncValue(aValue));
|
||
|
|
||
|
if not WasOpen then
|
||
|
Table.Close;
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableItem.Truncate;
|
||
|
begin
|
||
|
{ Make sure we suck in the dictionary before the table gets deleted }
|
||
|
GetDictionary;
|
||
|
with Table do begin
|
||
|
Close;
|
||
|
DeleteTable;
|
||
|
end;
|
||
|
Database.CreateTable(TableName, Dictionary);
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableItem.CopyRecords(aSrcTable: TffDataSet;
|
||
|
aCopyBLOBs: Boolean);
|
||
|
var
|
||
|
WasOpen : Boolean;
|
||
|
begin
|
||
|
WasOpen := Table.Active;
|
||
|
if not Table.Active then
|
||
|
Table.Open;
|
||
|
Table.CopyRecords(aSrcTable, aCopyBLOBs);
|
||
|
if not WasOpen then
|
||
|
Table.Close;
|
||
|
end;
|
||
|
{=====================================================================}
|
||
|
|
||
|
{== TffeTableList ====================================================}
|
||
|
constructor TffeTableList.Create(aDatabase : TffeDatabaseItem);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
FDatabase := aDatabase;
|
||
|
Sorted := False;
|
||
|
end;
|
||
|
{--------}
|
||
|
destructor TffeTableList.Destroy;
|
||
|
begin
|
||
|
Empty;
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeTableList.Add(const aTableName: TffName): longInt;
|
||
|
var
|
||
|
aTable : TffeTableItem;
|
||
|
begin
|
||
|
aTable := TffeTableItem.Create(FDatabase, aTableName);
|
||
|
Insert(aTable);
|
||
|
Result := pred(Count);
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableList.DropTable(aIndex: LongInt);
|
||
|
begin
|
||
|
with Items[aIndex].Table do begin
|
||
|
if Active then
|
||
|
Close;
|
||
|
DeleteTable;
|
||
|
end;
|
||
|
|
||
|
DeleteAt(aIndex);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeTableList.GetItem(aIndex: LongInt): TffeTableItem;
|
||
|
begin
|
||
|
Result := TffeTableItem(inherited Items[aIndex]);
|
||
|
end;
|
||
|
{--------}
|
||
|
function TffeTableList.Insert(aItem: TffeTableItem): Boolean;
|
||
|
begin
|
||
|
aItem.tiParentList := Self;
|
||
|
Result := inherited Insert(aItem);
|
||
|
end;
|
||
|
{--------}
|
||
|
procedure TffeTableList.Load;
|
||
|
var
|
||
|
I: Integer;
|
||
|
OldCursor: TCursor;
|
||
|
Tables: TStringList;
|
||
|
begin
|
||
|
Tables := TStringList.Create;
|
||
|
OldCursor := Screen.Cursor;
|
||
|
Screen.Cursor := crHourglass;
|
||
|
try
|
||
|
{ Remove any existing tables for this database }
|
||
|
Empty;
|
||
|
FDatabase.GetTableNames(Tables);
|
||
|
for I := 0 to Tables.Count - 1 do
|
||
|
Add(Tables[I]);
|
||
|
finally
|
||
|
Screen.Cursor := OldCursor;
|
||
|
Tables.Free;
|
||
|
end;
|
||
|
end;
|
||
|
{=====================================================================}
|
||
|
|
||
|
{ TffexpSession }
|
||
|
|
||
|
constructor TffexpSession.Create(AOwner: TComponent);
|
||
|
begin
|
||
|
inherited Create(AOwner);
|
||
|
|
||
|
OnLogin := FFELogin;
|
||
|
ffePassword := '';
|
||
|
ffeUserName := '';
|
||
|
end;
|
||
|
|
||
|
procedure TffexpSession.FFELogin(aSource: TObject; var aUserName,
|
||
|
aPassword: TffName; var aResult: Boolean);
|
||
|
var
|
||
|
FFLoginDialog : TffLoginDialog;
|
||
|
begin
|
||
|
FFLoginDialog := TFFLoginDialog.Create(nil);
|
||
|
try
|
||
|
with FFLoginDialog do begin
|
||
|
UserName := aUserName;
|
||
|
Password := aPassword;
|
||
|
ShowModal;
|
||
|
aResult := ModalResult = mrOK;
|
||
|
if aResult then begin
|
||
|
aUserName := UserName;
|
||
|
ffeUserName := UserName;
|
||
|
aPassword := Password;
|
||
|
ffePassword := Password;
|
||
|
aResult := True;
|
||
|
end;
|
||
|
end;
|
||
|
finally
|
||
|
FFLoginDialog.Free;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
initialization
|
||
|
NextEntitySerialKey := 0;
|
||
|
end.
|
||
|
|