Componentes.Terceros.jvcl/official/3.32/run/JvUIBMetaData.pas

2932 lines
88 KiB
ObjectPascal

{******************************************************************************}
{ UNIFIED INTERBASE (UIB) }
{ }
{ Project JEDI Code Library (JCL) }
{ }
{ 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 Initial Developer of the Original Code is documented in the accompanying }
{ help file JCL.chm. Portions created by these individuals are Copyright (C) }
{ 2003 of these individuals. }
{ }
{ Unit owner: Henri Gourvest }
{ Contributor: Ritsaert Hornstra }
{ Last modified: September 21, 2003 }
{ }
{******************************************************************************}
{ Class needed to read MetaData. }
{$I jvcl.inc}
{$I JvUIB.inc}
unit JvUIBMetaData;
interface
uses
{$IFDEF USEJVCL}
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
{$ENDIF USEJVCL}
Classes, SysUtils,
JvUIBase, JvUIBLib, JvUIB, JvUIBConst;
type
// (rom) the names of the elements need prefixes
TTriggerPrefix = (Before, After);
TTriggerSuffix = (Insert, Update, Delete);
TTriggerSuffixes = set of TTriggerSuffix;
TIndexOrder = (IoDescending, IoAscending);
TUpdateRule = (Restrict, Cascade, SetNull, SetDefault);
TTableFieldInfo = (fPrimary, fForeign, fIndice, fUnique);
TTableFieldInfos = set of TTableFieldInfo;
// indentation = inherit
TMetaNodeType =
(
MetaNode,
MetaDatabase,
MetaException,
MetaGenerator,
MetaCheck,
MetaTrigger,
MetaUDF,
MetaView,
MetaProcedure,
MetaRole,
MetaTable,
MetaBaseField,
MetaUDFField,
MetaField,
MetaProcInField,
MetaProcOutField,
MetaTableField,
MetaDomain,
MetaConstraint,
MetaForeign,
MetaIndex,
MetaPrimary,
MetaUnique
);
// forward declarations
TMetaNode = class;
TMetaDomain = class;
TMetaTable = class;
TMetaNodeClass = class of TMetaNode;
TNodeItem = record
Childs: TList;
ClassID: TMetaNodeClass;
end;
TMetaNode = class(TObject)
private
FName: string;
FOwner: TMetaNode;
FNodeItems: array of TNodeItem;
FNodeItemsCount: Integer;
function GetItems(const ClassIndex, Index: Integer): TMetaNode;
function GetAsDDL: string;
procedure AddClass(ClassID: TMetaNodeClass);
procedure CheckTransaction(Transaction: TJvUIBTransaction);
procedure SaveNode(Stream: TStringStream; OID: Integer; Separator: string = BreakLine);
procedure LoadFromStream(Stream: TStream); virtual; abstract;
function GetAsDDLNode: string;
public
procedure SaveToDDLNode(Stream: TStringStream); virtual;
function GetNodes(const Index: Integer): TNodeItem;
class function NodeClass: string; virtual;
class function NodeType: TMetaNodeType; virtual;
constructor Create(AOwner: TMetaNode; ClassIndex: Integer); virtual;
constructor CreateFromStream(AOwner: TMetaNode; ClassIndex: Integer; Stream: TStream); virtual;
destructor Destroy; override;
procedure SaveToStream(Stream: TStream); virtual;
procedure SaveToDDL(Stream: TStringStream); virtual;
property Name: string read FName;
property AsDDL: string read GetAsDDL;
property AsDDLNode: string read GetAsDDLNode;
property NodeCount: Integer read FNodeItemsCount;
property Nodes[const Index: Integer]: TNodeItem read GetNodes;
property Parent: TMetaNode read FOwner;
end;
TMetaGenerator = class(TMetaNode)
private
FValue: Integer;
procedure LoadFromDataBase(Transaction: TJvUIBTransaction; const Name: string);
procedure LoadFromStream(Stream: TStream); override;
public
procedure SaveToDDLNode(Stream: TStringStream); override;
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToStream(Stream: TStream); override;
property Value: Integer read FValue;
end;
TMetaBaseField = class(TMetaNode)
private
FScale: Word;
FLength: Smallint;
FPrecision: Smallint;
FFieldType: TUIBFieldType;
FCharSet: string;
FSegmentLength: Smallint;
FSubType: Smallint;
FBytesPerCharacter: Smallint;
procedure LoadFromQuery(QField, QCharset: TJvUIBStatement); virtual;
procedure LoadFromStream(Stream: TStream); override;
property SegmentLength: Smallint read FSegmentLength;
function GetShortFieldType: string;
public
procedure SaveToDDLNode(Stream: TStringStream); override;
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToStream(Stream: TStream); override;
property Scale: Word read FScale;
property Length: Smallint read FLength;
property Precision: Smallint read FPrecision;
property FieldType: TUIBFieldType read FFieldType;
property CharSet: string read FCharSet;
property SubType: Smallint read FSubType;
property BytesPerCharacter: Smallint read FBytesPerCharacter;
property ShortFieldType: string read GetShortFieldType;
end;
TMetaField = class(TMetaBaseField)
private
procedure LoadFromQuery(Q, C: TJvUIBStatement); override;
public
class function NodeType: TMetaNodeType; override;
procedure SaveToDDL(Stream: TStringStream); override;
property SegmentLength;
end;
TMetaProcInField = class(TMetaField)
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
end;
TMetaProcOutField = class(TMetaField)
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
end;
TMetaTableField = class(TMetaField)
private
FDefaultValue: string;
FNotNull: Boolean;
FDomain: Integer;
FInfos: TTableFieldInfos;
FComputedSource: string;
procedure LoadFromQuery(Q, C: TJvUIBStatement); override;
procedure LoadFromStream(Stream: TStream); override;
function GetDomain: TMetaDomain;
public
class function NodeType: TMetaNodeType; override;
procedure SaveToDDLNode(Stream: TStringStream); override;
procedure SaveToStream(Stream: TStream); override;
property DefaultValue: string read FDefaultValue;
property NotNull: Boolean read FNotNull;
property Domain: TMetaDomain read GetDomain;
property FieldInfos: TTableFieldInfos read FInfos;
property ComputedSource: string read FComputedSource;
end;
TMetaDomain = class(TMetaTableField)
protected
property Domain; // hidden
property ComputedSource; // hidden
public
procedure SaveToDDLNode(Stream: TStringStream); override;
procedure SaveToDDL(Stream: TStringStream); override;
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
end;
TMetaConstraint = class(TMetaNode)
private
FFields: array of Integer;
function GetFields(const Index: Word): TMetaTableField;
function GetFieldsCount: Word;
procedure LoadFromStream(Stream: TStream); override;
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToStream(Stream: TStream); override;
property Fields[const Index: Word]: TMetaTableField read GetFields;
property FieldsCount: Word read GetFieldsCount;
end;
TMetaPrimary = class(TMetaConstraint)
private
procedure LoadFromQuery(Q: TJvUIBStatement);
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToDDLNode(Stream: TStringStream); override;
end;
TMetaUnique = class(TMetaConstraint)
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToDDL(Stream: TStringStream); override;
end;
TMetaForeign = class(TMetaConstraint)
private
FForTable: Integer;
FForFields: array of Integer;
FOnDelete: TUpdateRule;
FOnUpdate: TUpdateRule;
function GetForFields(const Index: Word): TMetaTableField;
function GetForFieldsCount: Word;
function GetForTable: TMetaTable;
procedure LoadFromStream(Stream: TStream); override;
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToStream(Stream: TStream); override;
procedure SaveToDDLNode(Stream: TStringStream); override;
property ForTable: TMetaTable read GetForTable;
property ForFields[const Index: Word]: TMetaTableField read GetForFields;
property ForFieldsCount: Word read GetForFieldsCount;
property OnDelete: TUpdateRule read FOnDelete;
property OnUpdate: TUpdateRule read FOnUpdate;
end;
TMetaCheck = class(TMetaNode)
private
FConstraint: string;
procedure LoadFromStream(Stream: TStream); override;
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToDDLNode(Stream: TStringStream); override;
procedure SaveToStream(Stream: TStream); override;
property Constraint: string read FConstraint;
end;
TMetaIndex = class(TMetaConstraint)
private
FUnique: Boolean;
FActive: Boolean;
FOrder: TIndexOrder;
procedure LoadFromStream(Stream: TStream); override;
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToDDLNode(Stream: TStringStream); override;
procedure SaveToStream(Stream: TStream); override;
property Unique: Boolean read FUnique;
property Active: Boolean read FActive;
property Order: TIndexOrder read FOrder;
end;
TMetaTrigger = class(TMetaNode)
private
FPrefix: TTriggerPrefix;
FSuffix: TTriggerSuffixes;
FPosition: Smallint;
FActive: Boolean;
FSource: string;
class function DecodePrefix(Value: Integer): TTriggerPrefix;
class function DecodeSuffixes(Value: Integer): TTriggerSuffixes;
procedure LoadFromQuery(Q: TJvUIBStatement);
procedure LoadFromStream(Stream: TStream); override;
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToStream(Stream: TStream); override;
procedure SaveToDDLNode(Stream: TStringStream); override;
property Prefix: TTriggerPrefix read FPrefix;
property Suffix: TTriggerSuffixes read FSuffix;
property Position: Smallint read FPosition;
property Active: Boolean read FActive;
property Source: string read FSource;
end;
TMetaTable = class(TMetaNode)
private
function GetFields(const Index: Integer): TMetaTableField;
function GetFieldsCount: Integer;
procedure LoadFromDataBase(QNames, QFields, QCharset, QPrimary,
QIndex, QForeign, QCheck, QTrigger: TJvUIBStatement; OIDs: TOIDTables);
function FindFieldIndex(const Name: string): Integer;
function GetUniques(const Index: Integer): TMetaUnique;
function GetUniquesCount: Integer;
function GetPrimary(const Index: Integer): TMetaPrimary;
function GetPrimaryCount: Integer;
function GetIndices(const Index: Integer): TMetaIndex;
function GetIndicesCount: Integer;
function GetForeign(const Index: Integer): TMetaForeign;
function GetForeignCount: Integer;
function GetChecks(const Index: Integer): TMetaCheck;
function GetChecksCount: Integer;
function GetTriggers(const Index: Integer): TMetaTrigger;
function GetTriggersCount: Integer;
procedure LoadFromStream(Stream: TStream); override;
public
procedure SaveToDDLNode(Stream: TStringStream); override;
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
function FindFieldName(const Name: string): TMetaTableField;
constructor Create(AOwner: TMetaNode; ClassIndex: Integer); override;
procedure SaveToStream(Stream: TStream); override;
procedure SaveToDDL(Stream: TStringStream); override;
property Fields[const Index: Integer]: TMetaTableField read GetFields;
property FieldsCount: Integer read GetFieldsCount;
property Primary[const Index: Integer]: TMetaPrimary read GetPrimary;
property PrimaryCount: Integer read GetPrimaryCount; // 0 or 1
property Uniques[const Index: Integer]: TMetaUnique read GetUniques;
property UniquesCount: Integer read GetUniquesCount;
property Indices[const Index: Integer]: TMetaIndex read GetIndices;
property IndicesCount: Integer read GetIndicesCount;
property Foreign[const Index: Integer]: TMetaForeign read GetForeign;
property ForeignCount: Integer read GetForeignCount;
property Checks[const Index: Integer]: TMetaCheck read GetChecks;
property ChecksCount: Integer read GetChecksCount;
property Triggers[const Index: Integer]: TMetaTrigger read GetTriggers;
property TriggersCount: Integer read GetTriggersCount;
end;
TMetaView = class(TMetaNode)
private
FSource: string;
function GetFields(const Index: Integer): TMetaField;
function GetFieldsCount: Integer;
function GetTriggers(const Index: Integer): TMetaTrigger;
function GetTriggersCount: Integer;
procedure LoadFromDataBase(QName, QFields, QTriggers,
QCharset: TJvUIBStatement; OIDs: TOIDViews);
procedure LoadFromStream(Stream: TStream); override;
public
procedure SaveToDDLNode(Stream: TStringStream); override;
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
constructor Create(AOwner: TMetaNode; ClassIndex: Integer); override;
procedure SaveToStream(Stream: TStream); override;
procedure SaveToDDL(Stream: TStringStream); override;
property Source: string read FSource;
property Fields[const Index: Integer]: TMetaField read GetFields;
property FieldsCount: Integer read GetFieldsCount;
property Triggers[const Index: Integer]: TMetaTrigger read GetTriggers;
property TriggersCount: Integer read GetTriggersCount;
end;
TMetaProcedure = class(TMetaNode)
private
FSource: string;
procedure LoadFromQuery(QNames, QFields, QCharset: TJvUIBStatement; OIDs: TOIDProcedures);
function GetInputFields(const Index: Integer): TMetaProcInField;
function GetInputFieldsCount: Integer;
function GetOutputFields(const Index: Integer): TMetaProcOutField;
function GetOutputFieldsCount: Integer;
procedure LoadFromStream(Stream: TStream); override;
procedure InternalSaveToDDL(Stream: TStringStream; Operation: string);
procedure SaveToPostDDL(Stream: TStringStream);
public
procedure SaveToDDLNode(Stream: TStringStream); override;
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
constructor Create(AOwner: TMetaNode; ClassIndex: Integer); override;
procedure SaveToStream(Stream: TStream); override;
procedure SaveToAlterDDL(Stream: TStringStream);
property Source: string read FSource;
property InputFields[const Index: Integer]: TMetaProcInField read GetInputFields;
property InputFieldsCount: Integer read GetInputFieldsCount;
property OutputFields[const Index: Integer]: TMetaProcOutField read GetOutputFields;
property OutputFieldsCount: Integer read GetOutputFieldsCount;
end;
TMetaException = class(TMetaNode)
private
FMessage: string;
FNumber: Integer;
procedure LoadFromStream(Stream: TStream); override;
procedure LoadFromQuery(QName: TJvUIBStatement);
public
procedure SaveToDDLNode(Stream: TStringStream); override;
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToStream(Stream: TStream); override;
property Message: string read FMessage;
property Number: Integer read FNumber;
end;
TMetaUDFField = class(TMetaBaseField)
private
FPosition: Smallint;
FMechanism: Smallint;
procedure LoadFromQuery(QField, QCharset: TJvUIBStatement); override;
procedure LoadFromStream(Stream: TStream); override;
public
class function NodeType: TMetaNodeType; override;
procedure SaveToDDLNode(Stream: TStringStream); override;
procedure SaveToStream(Stream: TStream); override;
property Position: Smallint read FPosition;
property Mechanism: Smallint read FMechanism;
end;
TMetaUDF = class(TMetaNode)
private
FModule: string;
FEntry: string;
FReturn: Smallint;
procedure LoadFromStream(Stream: TStream); override;
procedure LoadFromQuery(QNames, QFields, QCharset: TJvUIBStatement; OIDs: TOIDUDFs);
function GetFields(const Index: Integer): TMetaUDFField;
function GetFieldsCount: Integer;
public
procedure SaveToDDLNode(Stream: TStringStream); override;
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
constructor Create(AOwner: TMetaNode; ClassIndex: Integer); override;
procedure SaveToStream(Stream: TStream); override;
property Module: string read FModule;
property Entry: string read FEntry;
property Return: Smallint read FReturn;
property Fields[const Index: Integer]: TMetaUDFField read GetFields;
property FieldsCount: Integer read GetFieldsCount;
end;
TMetaRole = class(TMetaNode)
private
FOwner: string;
procedure LoadFromStream(Stream: TStream); override;
procedure LoadFromQuery(QName: TJvUIBStatement);
public
procedure SaveToDDLNode(Stream: TStringStream); override;
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToStream(Stream: TStream); override;
property Owner: string read FOwner;
end;
TMetaDataBase = class(TMetaNode)
private
FOIDDatabases: TOIDDatabases;
FOIDTables: TOIDTables;
FOIDViews: TOIDViews;
FOIDProcedures: TOIDProcedures;
FOIDUDFs: TOIDUDFs;
FSysInfos: Boolean;
function GetGenerators(const Index: Integer): TMetaGenerator;
function GetGeneratorsCount: Integer;
function GetTables(const Index: Integer): TMetaTable;
function GetTablesCount: Integer;
function FindTableIndex(const TableName: string): Integer;
function FindDomainIndex(const DomainName: string): Integer;
function GetViews(const Index: Integer): TMetaView;
function GetViewsCount: Integer;
function GetDomains(const Index: Integer): TMetaDomain;
function GetDomainsCount: Integer;
procedure LoadFromStream(Stream: TStream); override;
function GetProcedures(const Index: Integer): TMetaProcedure;
function GetProceduresCount: Integer;
function GetExceptions(const Index: Integer): TMetaException;
function GetExceptionsCount: Integer;
function GetUDFS(const Index: Integer): TMetaUDF;
function GetUDFSCount: Integer;
function GetRoles(const Index: Integer): TMetaRole;
function GetRolesCount: Integer;
public
class function NodeClass: string; override;
class function NodeType: TMetaNodeType; override;
procedure SaveToStream(Stream: TStream); override;
function FindTableName(const TableName: string): TMetaTable;
function FindProcName(const ProcName: string): TMetaProcedure;
constructor Create(AOwner: TMetaNode; ClassIndex: Integer); override;
procedure LoadFromDatabase(Transaction: TJvUIBTransaction);
procedure SaveToDDL(Stream: TStringStream); override;
property OIDDatabases: TOIDDatabases read FOIDDatabases write FOIDDatabases;
property Generators[const Index: Integer]: TMetaGenerator read GetGenerators;
property GeneratorsCount: Integer read GetGeneratorsCount;
property Tables[const Index: Integer]: TMetaTable read GetTables;
property TablesCount: Integer read GetTablesCount;
property OIDTables: TOIDTables read FOIDTables write FOIDTables;
property Views[const Index: Integer]: TMetaView read GetViews;
property ViewsCount: Integer read GetViewsCount;
property OIDViews: TOIDViews read FOIDViews write FOIDViews;
property Domains[const Index: Integer]: TMetaDomain read GetDomains;
property DomainsCount: Integer read GetDomainsCount;
property Procedures[const Index: Integer]: TMetaProcedure read GetProcedures;
property ProceduresCount: Integer read GetProceduresCount;
property OIDProcedures: TOIDProcedures read FOIDProcedures write FOIDProcedures;
property Exceptions[const Index: Integer]: TMetaException read GetExceptions;
property ExceptionsCount: Integer read GetExceptionsCount;
property UDFS[const Index: Integer]: TMetaUDF read GetUDFS;
property UDFSCount: Integer read GetUDFSCount;
property OIDUDFs: TOIDUDFs read FOIDUDFs write FOIDUDFs;
property Roles[const Index: Integer]: TMetaRole read GetRoles;
property RolesCount: Integer read GetRolesCount;
property SysInfos: Boolean read FSysInfos write FSysInfos;
end;
{$IFDEF USEJVCL}
{$IFDEF UNITVERSIONING}
const
UnitVersioning: TUnitVersionInfo = (
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvUIBMetaData.pas $';
Revision: '$Revision: 10612 $';
Date: '$Date: 2006-05-19 21:04:09 +0200 (ven., 19 mai 2006) $';
LogPath: 'JVCL\run'
);
{$ENDIF UNITVERSIONING}
{$ENDIF USEJVCL}
implementation
// Database Tree
//------------------------
// OIDDomains = 0;
// OIDTable = 1;
// OIDTableFields = 0;
// OIDPrimary = 1;
// OIDForeign = 2;
// OIDTableTrigger = 3;
// OIDUnique = 4;
// OIDIndex = 5;
// OIDCheck = 6;
// OIDView = 2;
// OIDViewFields = 0;
// OIDViewTrigers = 1;
// OIDProcedure = 3;
// OIDProcFieldIn = 0;
// OIDProcFieldOut = 1;
// OIDGenerator = 4;
// OIDException = 5;
// OIDUDF = 6;
// OIDUDFField = 0;
// OIDRole = 7;
const
TriggerPrefixTypes: array [TTriggerPrefix] of PChar =
('BEFORE', 'AFTER');
TriggerSuffixTypes: array [TTriggerSuffix] of PChar =
('INSERT', 'UPDATE', 'DELETE');
FieldTypes: array [TUIBFieldType] of PChar =
('', 'NUMERIC', 'CHAR', 'VARCHAR', 'CSTRING', 'SMALLINT', 'INTEGER', 'QUAD',
'FLOAT', 'DOUBLE PRECISION', 'TIMESTAMP', 'BLOB', 'BLOBID', 'DATE', 'TIME',
'INT64' {$IFDEF IB7_UP}, 'BOOLEAN' {$ENDIF});
QRYGenerators =
'SELECT RDB$GENERATOR_NAME FROM RDB$GENERATORS GEN WHERE ' +
'(NOT GEN.RDB$GENERATOR_NAME STARTING WITH ''RDB$'') AND ' +
'(NOT GEN.RDB$GENERATOR_NAME STARTING WITH ''SQL$'') AND ' +
'((GEN.RDB$SYSTEM_FLAG IS NULL) OR (GEN.RDB$SYSTEM_FLAG <> 1)) ' +
'ORDER BY GEN.RDB$GENERATOR_NAME';
QRYTables =
'SELECT REL.RDB$RELATION_NAME FROM RDB$RELATIONS REL WHERE ' +
'(REL.RDB$SYSTEM_FLAG <> 1 OR REL.RDB$SYSTEM_FLAG IS NULL) AND ' +
'(NOT REL.RDB$FLAGS IS NULL) AND ' +
'(REL.RDB$VIEW_BLR IS NULL) AND ' +
'(REL.RDB$SECURITY_CLASS STARTING WITH ''SQL$'') ' +
'ORDER BY REL.RDB$RELATION_NAME';
QRYSysTables =
'SELECT REL.RDB$RELATION_NAME FROM RDB$RELATIONS REL ' +
'WHERE REL.RDB$VIEW_BLR IS NULL ORDER BY REL.RDB$RELATION_NAME';
QRYTableFields =
'SELECT FLD.RDB$FIELD_TYPE, FLD.RDB$FIELD_SCALE, ' +
'FLD.RDB$FIELD_LENGTH, FLD.RDB$FIELD_PRECISION, ' +
'FLD.RDB$CHARACTER_SET_ID, FLD.RDB$FIELD_SUB_TYPE, RFR.RDB$FIELD_NAME, ' +
'FLD.RDB$SEGMENT_LENGTH, RFR.RDB$NULL_FLAG, RFR.RDB$DEFAULT_SOURCE, ' +
'RFR.RDB$FIELD_SOURCE , FLD.RDB$COMPUTED_SOURCE ' +
'FROM RDB$RELATIONS REL, RDB$RELATION_FIELDS RFR, RDB$FIELDS FLD ' +
'WHERE (RFR.RDB$FIELD_SOURCE = FLD.RDB$FIELD_NAME) AND ' +
'(RFR.RDB$RELATION_NAME = REL.RDB$RELATION_NAME) AND ' +
'(REL.RDB$RELATION_NAME = ?) ' +
'ORDER BY RFR.RDB$FIELD_POSITION, RFR.RDB$FIELD_NAME';
QRYCharset =
'SELECT RDB$CHARACTER_SET_ID, RDB$CHARACTER_SET_NAME, RDB$BYTES_PER_CHARACTER FROM RDB$CHARACTER_SETS';
QRYUnique =
'SELECT RC.RDB$CONSTRAINT_NAME, IDX.RDB$FIELD_NAME ' +
'FROM RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS IDX ' +
'WHERE (IDX.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) AND ' +
'(RC.RDB$CONSTRAINT_TYPE = ?) ' +
'AND (RC.RDB$RELATION_NAME = ?) ' +
'ORDER BY RC.RDB$RELATION_NAME, IDX.RDB$FIELD_POSITION';
QRYIndex =
'SELECT IDX.RDB$INDEX_NAME, ISG.RDB$FIELD_NAME, IDX.RDB$UNIQUE_FLAG, ' +
'IDX.RDB$INDEX_INACTIVE, IDX.RDB$INDEX_TYPE FROM RDB$INDICES IDX ' +
'LEFT JOIN RDB$INDEX_SEGMENTS ISG ON ISG.RDB$INDEX_NAME = IDX.RDB$INDEX_NAME ' +
'LEFT JOIN RDB$RELATION_CONSTRAINTS C ON IDX.RDB$INDEX_NAME = C.RDB$INDEX_NAME ' +
'WHERE (C.RDB$CONSTRAINT_NAME IS NULL) AND (IDX.RDB$RELATION_NAME = ?) ' +
'ORDER BY IDX.RDB$RELATION_NAME, IDX.RDB$INDEX_NAME, ISG.RDB$FIELD_POSITION';
QRYForeign =
'SELECT A.RDB$CONSTRAINT_NAME, B.RDB$UPDATE_RULE, B.RDB$DELETE_RULE, ' +
'C.RDB$RELATION_NAME AS FK_TABLE, D.RDB$FIELD_NAME AS FK_FIELD, ' +
'E.RDB$FIELD_NAME AS ONFIELD ' +
'FROM RDB$REF_CONSTRAINTS B, RDB$RELATION_CONSTRAINTS A, RDB$RELATION_CONSTRAINTS C, ' +
'RDB$INDEX_SEGMENTS D, RDB$INDEX_SEGMENTS E ' +
'WHERE (A.RDB$CONSTRAINT_TYPE = ''FOREIGN KEY'') AND ' +
'(A.RDB$CONSTRAINT_NAME = B.RDB$CONSTRAINT_NAME) AND ' +
'(B.RDB$CONST_NAME_UQ=C.RDB$CONSTRAINT_NAME) AND (C.RDB$INDEX_NAME=D.RDB$INDEX_NAME) AND ' +
'(A.RDB$INDEX_NAME=E.RDB$INDEX_NAME) AND ' +
'(D.RDB$FIELD_POSITION = E.RDB$FIELD_POSITION) ' +
'AND (A.RDB$RELATION_NAME = ?) ' +
'ORDER BY A.RDB$CONSTRAINT_NAME, A.RDB$RELATION_NAME, D.RDB$FIELD_POSITION, E.RDB$FIELD_POSITION';
QRYCheck =
'SELECT A.RDB$CONSTRAINT_NAME, C.RDB$TRIGGER_SOURCE ' +
'FROM RDB$RELATION_CONSTRAINTS A, RDB$CHECK_CONSTRAINTS B, RDB$TRIGGERS C ' +
'WHERE (A.RDB$CONSTRAINT_TYPE = ''CHECK'') AND ' +
'(A.RDB$CONSTRAINT_NAME = B.RDB$CONSTRAINT_NAME) AND ' +
'(B.RDB$TRIGGER_NAME = C.RDB$TRIGGER_NAME) AND ' +
'(C.RDB$TRIGGER_TYPE = 1) ' +
'AND (A.RDB$RELATION_NAME = ?)';
QRYTrigger =
'SELECT T.RDB$TRIGGER_NAME, T.RDB$TRIGGER_SOURCE, T.RDB$TRIGGER_SEQUENCE, ' +
'T.RDB$TRIGGER_TYPE, T.RDB$TRIGGER_INACTIVE, T.RDB$SYSTEM_FLAG ' +
'from RDB$TRIGGERS T left join RDB$CHECK_CONSTRAINTS C ON C.RDB$TRIGGER_NAME = ' +
'T.RDB$TRIGGER_NAME where ((T.RDB$SYSTEM_FLAG = 0) or (T.RDB$SYSTEM_FLAG is null)) ' +
'and (c.rdb$trigger_name is null) and (T.RDB$RELATION_NAME = ?) ' +
'order by T.RDB$TRIGGER_NAME';
QRYSysTrigger =
'SELECT T.RDB$TRIGGER_NAME, T.RDB$TRIGGER_SOURCE, T.RDB$TRIGGER_SEQUENCE, ' +
'T.RDB$TRIGGER_TYPE, T.RDB$TRIGGER_INACTIVE, T.RDB$SYSTEM_FLAG ' +
'FROM RDB$TRIGGERS T LEFT JOIN RDB$CHECK_CONSTRAINTS C ON C.RDB$TRIGGER_NAME = ' +
'T.RDB$TRIGGER_NAME WHERE (T.RDB$RELATION_NAME = ?) ORDER BY T.RDB$TRIGGER_NAME';
QRYView =
'SELECT REL.RDB$RELATION_NAME, REL.RDB$VIEW_SOURCE FROM RDB$RELATIONS REL WHERE ' +
'(REL.RDB$SYSTEM_FLAG <> 1 OR REL.RDB$SYSTEM_FLAG IS NULL) AND ' +
'(NOT REL.RDB$FLAGS IS NULL) AND ' +
'(NOT REL.RDB$VIEW_BLR IS NULL) AND ' +
'(REL.RDB$SECURITY_CLASS STARTING WITH ''SQL$'') ' +
'ORDER BY REL.RDB$RELATION_NAME';
QRYDomains =
'select RDB$FIELD_TYPE, RDB$FIELD_SCALE, RDB$FIELD_LENGTH, ' +
'RDB$FIELD_PRECISION, RDB$CHARACTER_SET_ID, RDB$FIELD_SUB_TYPE, ' +
'RDB$FIELD_NAME, RDB$SEGMENT_LENGTH, RDB$NULL_FLAG, RDB$DEFAULT_SOURCE, RDB$COMPUTED_SOURCE ' +
'FROM RDB$FIELDS WHERE NOT (RDB$FIELD_NAME STARTING WITH ''RDB$'')';
QRYSysDomains =
'select RDB$FIELD_TYPE, RDB$FIELD_SCALE, RDB$FIELD_LENGTH, ' +
'RDB$FIELD_PRECISION, RDB$CHARACTER_SET_ID, RDB$FIELD_SUB_TYPE, ' +
'RDB$FIELD_NAME, RDB$SEGMENT_LENGTH, RDB$NULL_FLAG, RDB$DEFAULT_SOURCE, RDB$COMPUTED_SOURCE ' +
'from RDB$FIELDS';
QRYProcedures =
'SELECT RDB$PROCEDURE_NAME, RDB$PROCEDURE_SOURCE FROM RDB$PROCEDURES ORDER BY RDB$PROCEDURE_NAME';
QRYProcFields =
'SELECT FS.RDB$FIELD_TYPE, FS.RDB$FIELD_SCALE, FS.RDB$FIELD_LENGTH, FS.RDB$FIELD_PRECISION, ' +
'FS.RDB$CHARACTER_SET_ID, FS.RDB$FIELD_SUB_TYPE, PP.RDB$PARAMETER_NAME, FS.RDB$SEGMENT_LENGTH ' +
'FROM RDB$PROCEDURES PR LEFT JOIN RDB$PROCEDURE_PARAMETERS PP ' +
'ON PP.RDB$PROCEDURE_NAME = PR.RDB$PROCEDURE_NAME LEFT JOIN RDB$FIELDS FS ON ' +
'FS.RDB$FIELD_NAME = PP.RDB$FIELD_SOURCE LEFT JOIN RDB$CHARACTER_SETS CR ON ' +
'FS.RDB$CHARACTER_SET_ID = CR.RDB$CHARACTER_SET_ID LEFT JOIN RDB$COLLATIONS CO ' +
'ON ((FS.RDB$COLLATION_ID = CO.RDB$COLLATION_ID) AND (FS.RDB$CHARACTER_SET_ID = ' +
'CO.RDB$CHARACTER_SET_ID)) WHERE (PR.RDB$PROCEDURE_NAME = ?) AND ' +
'(PP.RDB$PARAMETER_TYPE = ?) ORDER BY PP.RDB$PARAMETER_TYPE, PP.RDB$PARAMETER_NUMBER';
QRYExceptions =
'SELECT RDB$EXCEPTION_NAME, RDB$MESSAGE, RDB$EXCEPTION_NUMBER FROM RDB$EXCEPTIONS ORDER BY RDB$EXCEPTION_NAME';
QRYUDF =
'SELECT RDB$FUNCTION_NAME, RDB$MODULE_NAME, RDB$ENTRYPOINT, RDB$RETURN_ARGUMENT ' +
'FROM RDB$FUNCTIONS WHERE (RDB$SYSTEM_FLAG IS NULL) ORDER BY RDB$FUNCTION_NAME';
QRYUDFFields =
'SELECT RDB$FIELD_TYPE, RDB$FIELD_SCALE, RDB$FIELD_LENGTH, RDB$FIELD_PRECISION, ' +
'RDB$CHARACTER_SET_ID, RDB$FIELD_SUB_TYPE, RDB$ARGUMENT_POSITION, RDB$MECHANISM ' +
'FROM RDB$FUNCTION_ARGUMENTS WHERE RDB$FUNCTION_NAME = ? ' +
'ORDER BY RDB$ARGUMENT_POSITION';
QRYRoles =
'SELECT RDB$ROLE_NAME, RDB$OWNER_NAME FROM RDB$ROLES';
procedure WriteString(Stream: TStream; var Str: string);
var
Len: Integer;
begin
Len := Length(Str);
Stream.Write(Len, SizeOf(Len));
if Len > 0 then
Stream.Write(PChar(Str)^, Len);
end;
procedure ReadString(Stream: TStream; var Str: string);
var
Len: Integer;
begin
Stream.Read(Len, SizeOf(Len));
SetLength(Str, Len);
if Len > 0 then
Stream.Read(PChar(Str)^, Len);
end;
//=== { TMetaNode } ==========================================================
constructor TMetaNode.Create(AOwner: TMetaNode; ClassIndex: Integer);
begin
// (rom) added inherited Create
inherited Create;
FNodeItemsCount := 0;
FOwner := AOwner;
if (FOwner <> nil) and (ClassIndex >= 0) then
FOwner.FNodeItems[ClassIndex].Childs.Add(Self)
end;
constructor TMetaNode.CreateFromStream(AOwner: TMetaNode; ClassIndex: Integer; Stream: TStream);
var
I, J: Integer;
begin
Create(AOwner, ClassIndex);
LoadFromStream(Stream);
for J := 0 to FNodeItemsCount - 1 do
begin
Stream.Read(I, SizeOf(I));
for I := 0 to I - 1 do
FNodeItems[J].ClassID.CreateFromStream(Self, J, Stream);
end;
end;
destructor TMetaNode.Destroy;
var
I, J: Integer;
begin
for I := 0 to FNodeItemsCount - 1 do
begin
for J := 0 to FNodeItems[I].Childs.Count - 1 do
TObJect(FNodeItems[I].Childs[J]).Free;
FNodeItems[I].Childs.Free;
end;
inherited Destroy;
end;
function TMetaNode.GetAsDDL: string;
var
Stream: TStringStream;
begin
Stream := TStringStream.Create('');
try
SaveToDDL(Stream);
Result := Stream.DataString;
finally
Stream.Free;
end;
end;
function TMetaNode.GetItems(const ClassIndex, Index: Integer): TMetaNode;
var
FChilds: TList;
begin
FChilds := FNodeItems[ClassIndex].Childs;
if (FChilds.Count > 0) and (Index >= 0) and
(Index < FChilds.Count) then
Result := TMetaNode(FChilds.Items[Index])
else
raise EUIBError.CreateFmt(EUIB_INDEXERROR, [Index]);
end;
procedure TMetaNode.SaveToStream(Stream: TStream);
var
I, J: Integer;
begin
for J := 0 to FNodeItemsCount - 1 do
begin
I := FNodeItems[J].Childs.Count;
Stream.Write(I, SizeOf(I));
for I := 0 to I - 1 do
TMetaNode(FNodeItems[J].Childs.Items[I]).SaveToStream(Stream);
end;
end;
procedure TMetaNode.AddClass(ClassID: TMetaNodeClass);
begin
SetLength(FNodeItems, FNodeItemsCount + 1);
FNodeItems[FNodeItemsCount].Childs := TList.Create;
FNodeItems[FNodeItemsCount].ClassID := ClassID;
Inc(FNodeItemsCount);
end;
procedure TMetaNode.CheckTransaction(Transaction: TJvUIBTransaction);
begin
Assert(Transaction <> nil);
Assert(Transaction.DataBase <> nil);
end;
procedure TMetaNode.SaveNode(Stream: TStringStream; OID: Integer;
Separator: string);
var
I: Integer;
begin
for I := 0 to FNodeItems[OID].Childs.Count - 1 do
begin
if I = 0 then
Stream.WriteString(NewLine)
else
Stream.WriteString(Separator);
TMetaNode(FNodeItems[OID].Childs[I]).SaveToDDL(Stream);
end;
end;
procedure TMetaNode.SaveToDDLNode(Stream: TStringStream);
begin
end;
function TMetaNode.GetNodes(const Index: Integer): TNodeItem;
begin
Assert((Index >= 0) and (FNodeItemsCount > 0) and (Index < FNodeItemsCount));
Result := FNodeItems[Index];
end;
class function TMetaNode.NodeClass: string;
begin
Result := 'Node'
end;
procedure TMetaNode.SaveToDDL(Stream: TStringStream);
begin
SaveToDDLNode(Stream);
end;
function TMetaNode.GetAsDDLNode: string;
var
Stream: TStringStream;
begin
Stream := TStringStream.Create('');
try
SaveToDDLNode(Stream);
Result := Stream.DataString;
finally
Stream.Free;
end;
end;
class function TMetaNode.NodeType: TMetaNodeType;
begin
Result := MetaNode;
end;
//=== { TMetaGenerator } =====================================================
procedure TMetaGenerator.LoadFromDataBase(Transaction: TJvUIBTransaction;
const Name: string);
var
Query: TJvUIBStatement;
begin
CheckTransaction(Transaction);
Query := TJvUIBStatement.Create(nil);
Query.Transaction := Transaction;
Query.CachedFetch := False;
try
FName := Name;
Query.SQL.Text := Format('select gen_id(%s, 0) from rdb$database', [FName]);
Query.Open;
if not Query.Eof then
FValue := Query.Fields.AsInteger[0]
else
raise EUIBError.CreateFmt(EUIB_NOGENERATOR, [FName]);
finally
Query.Free;
end;
end;
procedure TMetaGenerator.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
Stream.Read(FValue, SizeOf(FValue));
end;
procedure TMetaGenerator.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
Stream.Write(FValue, SizeOf(FValue));
end;
procedure TMetaGenerator.SaveToDDLNode(Stream: TStringStream);
begin
Stream.WriteString(Format(
'CREATE GENERATOR %s;%sSET GENERATOR %0:s TO %2:d;',
[FName, BreakLine, FValue]));
end;
class function TMetaGenerator.NodeClass: string;
begin
Result := 'Generator';
end;
class function TMetaGenerator.NodeType: TMetaNodeType;
begin
Result := MetaGenerator;
end;
//=== { TMetaTable } =========================================================
constructor TMetaTable.Create(AOwner: TMetaNode; ClassIndex: Integer);
begin
inherited Create(AOwner, ClassIndex);
AddClass(TMetaTableField);
AddClass(TMetaPrimary);
AddClass(TMetaForeign);
AddClass(TMetaTrigger);
AddClass(TMetaUnique);
AddClass(TMetaIndex);
AddClass(TMetaCheck);
end;
function TMetaTable.FindFieldName(const Name: string): TMetaTableField;
var
I: Integer;
begin
for I := 0 to FieldsCount - 1 do
if Fields[I].FName = Name then
begin
Result := Fields[I];
Exit;
end;
raise EUIBError.CreateFmt(EUIB_NOFIELD, [Name]);
end;
function TMetaTable.GetFields(const Index: Integer): TMetaTableField;
begin
Result := TMetaTableField(GetItems(Ord(OIDTableField), Index))
end;
function TMetaTable.GetFieldsCount: Integer;
begin
Result := FNodeItems[Ord(OIDTableField)].Childs.Count;
end;
function TMetaTable.GetPrimary(const Index: Integer): TMetaPrimary;
begin
Result := TMetaPrimary(GetItems(Ord(OIDPrimary), Index))
end;
function TMetaTable.GetPrimaryCount: Integer;
begin
Result := FNodeItems[Ord(OIDPrimary)].Childs.Count;
end;
function TMetaTable.GetUniques(const Index: Integer): TMetaUnique;
begin
Result := TMetaUnique(GetItems(Ord(OIDUnique), Index))
end;
function TMetaTable.GetUniquesCount: Integer;
begin
Result := FNodeItems[Ord(OIDUnique)].Childs.Count;
end;
procedure TMetaTable.LoadFromDataBase(QNames, QFields, QCharset, QPrimary,
QIndex, QForeign, QCheck, QTrigger: TJvUIBStatement; OIDs: TOIDTables);
var
Unk: string;
begin
// Fields
FName := Trim(QNames.Fields.AsString[0]);
if OIDTableField in OIDs then
begin
QFields.Params.AsString[0] := FName;
QFields.Open;
while not QFields.Eof do
begin
with TMetaTableField.Create(Self, Ord(OIDTableField)) do
LoadFromQuery(QFields, QCharset);
QFields.Next;
end;
// PRIMARY
if OIDPrimary in OIDs then
begin
QPrimary.Params.AsString[1] := FName;
QPrimary.Params.AsString[0] := 'PRIMARY KEY';
QPrimary.Open;
if not QPrimary.Eof then
TMetaPrimary.Create(Self, Ord(OIDPrimary)).LoadFromQuery(QPrimary);
end;
// INDICES
if OIDIndex in OIDs then
begin
Unk := '';
QIndex.Params.AsString[0] := FName;
QIndex.Open;
while not QIndex.Eof do
begin
if Unk <> Trim(QIndex.Fields.AsString[0]) then
with TMetaIndex.Create(Self, Ord(OIDIndex)) do
begin
SetLength(FFields, 1);
FName := Trim(QIndex.Fields.AsString[0]);
FFields[0] := FindFieldIndex(Trim(QIndex.Fields.AsString[1]));
FUnique := QIndex.Fields.AsSingle[2] = 1;
FActive := QIndex.Fields.AsSingle[3] = 0;
if QIndex.Fields.AsSingle[4] = 0 then
FOrder := IoAscending
else
FOrder := IoDescending;
Unk := FName;
end
else
with Indices[IndicesCount - 1] do
begin
SetLength(FFields, FieldsCount + 1);
FFields[FieldsCount - 1] := FindFieldIndex(Trim(QIndex.Fields.AsString[1]));
Include(Fields[FieldsCount - 1].FInfos, fIndice);
end;
QIndex.Next;
end;
end;
// UNIQUE
if OIDUnique in OIDs then
begin
QPrimary.Params.AsString[0] := 'UNIQUE';
if not (OIDPrimary in OIDs) then
QPrimary.Params.AsString[1] := FName;
QPrimary.Open;
while not QPrimary.Eof do
begin
if Unk <> Trim(QPrimary.Fields.AsString[0]) then
with TMetaUnique.Create(Self, Ord(OIDUnique)) do
begin
SetLength(FFields, 1);
FName := Trim(QPrimary.Fields.AsString[0]);
FFields[0] := FindFieldIndex(Trim(QPrimary.Fields.AsString[1]));
Unk := FName;
end
else
with Uniques[UniquesCount - 1] do
begin
SetLength(FFields, FieldsCount + 1);
FFields[FieldsCount - 1] := FindFieldIndex(Trim(QPrimary.Fields.AsString[1]));
Include(Fields[FieldsCount - 1].FInfos, fUnique);
end;
QPrimary.Next;
end;
end;
end;
// Check
if OIDCheck in OIDs then
begin
QCheck.Params.AsString[0] := FName;
QCheck.Open;
while not QCheck.Eof do
with TMetaCheck.Create(Self, Ord(OIDCheck)) do
begin
FName := Trim(QCheck.Fields.AsString[0]);
QCheck.ReadBlob(1, FConstraint);
QCheck.Next;
end;
end;
// TRIGGER
if OIDTableTrigger in OIDs then
begin
QTrigger.Params.AsString[0] := FName;
QTrigger.Open;
while not QTrigger.Eof do
begin
TMetaTrigger.Create(Self, Ord(OIDTableTrigger)).LoadFromQuery(QTrigger);
QTrigger.Next;
end;
end;
end;
procedure TMetaTable.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
end;
procedure TMetaTable.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
inherited SaveToStream(Stream);
end;
procedure TMetaTable.SaveToDDL(Stream: TStringStream);
begin
inherited SaveToDDL(Stream);
SaveNode(Stream, Ord(OIDPrimary));
SaveNode(Stream, Ord(OIDUnique));
SaveNode(Stream, Ord(OIDIndex));
SaveNode(Stream, Ord(OIDForeign));
SaveNode(Stream, Ord(OIDCheck));
SaveNode(Stream, Ord(OIDTableTrigger), NewLine);
end;
function TMetaTable.GetIndices(const Index: Integer): TMetaIndex;
begin
Result := TMetaIndex(GetItems(Ord(OIDIndex), Index))
end;
function TMetaTable.GetIndicesCount: Integer;
begin
Result := FNodeItems[Ord(OIDIndex)].Childs.Count;
end;
function TMetaTable.GetForeign(const Index: Integer): TMetaForeign;
begin
Result := TMetaForeign(GetItems(Ord(OIDForeign), Index))
end;
function TMetaTable.GetForeignCount: Integer;
begin
Result := FNodeItems[Ord(OIDForeign)].Childs.Count;
end;
function TMetaTable.FindFieldIndex(const Name: string): Integer;
begin
for Result := 0 to FieldsCount - 1 do
if Fields[Result].FName = Name then
Exit;
raise EUIBError.CreateFmt(EUIB_FIELDSTRNOTFOUND, [Name]);
end;
function TMetaTable.GetChecks(const Index: Integer): TMetaCheck;
begin
Result := TMetaCheck(GetItems(Ord(OIDCheck), Index));
end;
function TMetaTable.GetChecksCount: Integer;
begin
Result := FNodeItems[Ord(OIDCheck)].Childs.Count;
end;
function TMetaTable.GetTriggers(const Index: Integer): TMetaTrigger;
begin
Result := TMetaTrigger(GetItems(Ord(OIDTableTrigger), Index));
end;
function TMetaTable.GetTriggersCount: Integer;
begin
Result := FNodeItems[Ord(OIDTableTrigger)].Childs.Count;
end;
procedure TMetaTable.SaveToDDLNode(Stream: TStringStream);
var
I: Integer;
begin
Stream.WriteString(Format('CREATE TABLE %s (', [FName]));
for I := 0 to FieldsCount - 1 do
begin
Stream.WriteString(BreakLine + ' ');
Fields[I].SaveToDDL(Stream);
if I <> FieldsCount - 1 then
Stream.WriteString(',');
end;
Stream.WriteString(BreakLine + ');');
end;
class function TMetaTable.NodeClass: string;
begin
Result := 'Table';
end;
class function TMetaTable.NodeType: TMetaNodeType;
begin
Result := MetaTable;
end;
//=== { TMetaBaseField } =====================================================
procedure TMetaBaseField.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
Stream.Read(FFieldType, SizeOf(FFieldType));
if FFieldType = uftNumeric then
begin
Stream.Read(FScale, SizeOf(FScale));
Stream.Read(FPrecision, SizeOf(FPrecision));
end
else
begin
FScale := 0;
FPrecision := 0;
end;
if FFieldType in [uftChar..uftCstring] then
begin
Stream.Read(FLength, SizeOf(FLength));
ReadString(Stream, FCharSet);
Stream.Read(FBytesPerCharacter, SizeOf(FBytesPerCharacter));
end
else
begin
FLength := 0;
FCharSet := '';
end;
if FFieldType = uftBlob then
begin
Stream.Read(FSegmentLength, SizeOf(FSegmentLength));
Stream.Read(FSubType, SizeOf(FSubType));
end
else
begin
FSegmentLength := 0;
FSubType := 0;
end;
end;
procedure TMetaBaseField.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
Stream.Write(FFieldType, SizeOf(FFieldType));
if FFieldType = uftNumeric then
begin
Stream.Write(FScale, SizeOf(FScale));
Stream.Write(FPrecision, SizeOf(FPrecision));
end;
if FFieldType in [uftChar..uftCstring] then
begin
Stream.Write(FLength, SizeOf(FLength));
WriteString(Stream, FCharSet);
Stream.Write(FBytesPerCharacter, SizeOf(FBytesPerCharacter));
end;
if FFieldType = uftBlob then
begin
Stream.Write(FSegmentLength, SizeOf(FSegmentLength));
Stream.Write(FSubType, SizeOf(FSubType));
end;
end;
procedure TMetaBaseField.LoadFromQuery(QField, QCharset: TJvUIBStatement);
procedure FindCharset(const Id: Single; var Charset: string; var Count: Smallint);
var
I: Integer;
begin
for I := 0 to QCharset.Fields.RecordCount - 1 do
begin
QCharset.Fields.GetRecord(I);
if QCharset.Fields.AsSmallint[0] = Id then
begin
Charset := Trim(QCharset.Fields.AsString[1]);
Count := QCharset.Fields.AsSmallint[2];
Exit;
end;
Charset := '';
FBytesPerCharacter := 1;
end;
end;
begin
FScale := Abs(QField.Fields.AsSmallInt[1]);
FLength := QField.Fields.AsSmallInt[2];
FPrecision := QField.Fields.AsSmallInt[3];
if FScale > 0 then
begin
FFieldType := uftNumeric;
if FPrecision = 0 then
case QField.Fields.AsSmallint[0] of
blr_short:
FPrecision := 4;
blr_long:
FPrecision := 7;
blr_int64, blr_quad, blr_double:
FPrecision := 15;
else
raise EUIBError.Create(EUIB_UNEXPECTEDERROR);
end;
end
else
case QField.Fields.AsSmallint[0] of
blr_text, blr_text2:
FFieldType := uftChar;
blr_varying, blr_varying2:
FFieldType := uftVarchar;
blr_cstring, blr_cstring2:
FFieldType := uftCstring;
blr_short:
FFieldType := uftSmallint;
blr_long:
FFieldType := uftInteger;
blr_quad:
FFieldType := uftQuad;
blr_float, blr_d_float:
FFieldType := uftFloat;
blr_double:
FFieldType := uftDoublePrecision;
blr_timestamp:
FFieldType := uftTimestamp;
blr_blob:
FFieldType := uftBlob;
blr_blob_id:
FFieldType := uftBlobId;
blr_sql_date:
FFieldType := uftDate;
blr_sql_time:
FFieldType := uftTime;
blr_int64:
FFieldType := uftInt64;
{$IFDEF IB7_UP}
blr_boolean_dtype:
FFieldType := uftBoolean;
{$ENDIF IB7_UP}
end;
if (FFieldType in [uftChar, uftVarchar, uftCstring]) and
not QField.Fields.IsNull[4] then
FindCharset(QField.Fields.AsSmallint[4], FCharSet, FBytesPerCharacter)
else
FBytesPerCharacter := 1;
FSubType := QField.Fields.AsSmallint[5];
end;
procedure TMetaBaseField.SaveToDDLNode(Stream: TStringStream);
begin
case FFieldType of
uftNumeric:
Stream.WriteString(Format('%s(%d,%d)',
[FieldTypes[FFieldType], FPrecision, FScale]));
uftChar..uftCstring:
begin
Stream.WriteString(Format('%s(%d)',
[FieldTypes[FFieldType], FLength div FBytesPerCharacter]));
if FCharSet <> '' then
Stream.WriteString(' CHARACTER SET ' + FCharSet);
end;
uftBlob:
Stream.WriteString(Format('%s SUB_TYPE %d SEGMENT SIZE %d',
[FieldTypes[FFieldType], FSubType, FSegmentLength]));
else
Stream.WriteString(Format('%s', [FieldTypes[FFieldType]]));
end;
end;
class function TMetaBaseField.NodeClass: string;
begin
Result := 'Field';
end;
function TMetaBaseField.GetShortFieldType: string;
begin
case FFieldType of
uftChar..uftCstring:
Result := Format('%s(%d)', [FieldTypes[FFieldType],
FLength div FBytesPerCharacter]);
uftNumeric:
Result := Format('%s(%d,%d)',
[FieldTypes[FFieldType], FPrecision, FScale]);
else
Result := Format('%s', [FieldTypes[FFieldType]]);
end;
end;
class function TMetaBaseField.NodeType: TMetaNodeType;
begin
Result := MetaBaseField;
end;
//=== { TMetaDataBase } ======================================================
constructor TMetaDataBase.Create(AOwner: TMetaNode; ClassIndex: Integer);
begin
inherited Create(nil, -1);
AddClass(TMetaDomain);
AddClass(TMetaTable);
AddClass(TMetaView);
AddClass(TMetaProcedure);
AddClass(TMetaGenerator);
AddClass(TMetaException);
AddClass(TMetaUDF);
AddClass(TMetaRole);
FOIDDatabases := ALLOBjects;
FOIDTables := ALLTables;
FOIDViews := ALLViews;
FOIDProcedures := ALLProcedures;
FOIDUDFs := ALLUDFs;
FSysInfos := False;
end;
procedure TMetaDataBase.LoadFromDatabase(Transaction: TJvUIBTransaction);
var
I: Integer;
ConStr, Str: string;
QNames, QFields, QCharset, QPrimary: TJvUIBStatement;
QIndex, QForeign, QCheck, QTrigger: TJvUIBStatement;
procedure Configure(var Q: TJvUIBStatement; const Qry: string;
CachedFetch: Boolean = False);
begin
Q := TJvUIBStatement.Create(nil);
Q.Transaction := Transaction;
Q.CachedFetch := CachedFetch;
Q.SQL.Text := Qry;
end;
begin
CheckTransaction(Transaction);
FName := Transaction.DataBase.DatabaseName;
Configure(QNames, '');
if FSysInfos then
Configure(QTrigger, QRYSysTrigger)
else
Configure(QTrigger, QRYTrigger);
Configure(QCharset, QRYCharset, True);
Configure(QFields, QRYTableFields);
Configure(QPrimary, QRYUnique, True);
Configure(QIndex, QRYIndex);
Configure(QForeign, QRYForeign);
Configure(QCheck, QRYCheck);
try
// preload Charsets
QCharset.Open;
QCharset.FetchAll;
// DOMAINS
if OIDDomain in FOIDDatabases then
begin
FNodeItems[Ord(OIDDomain)].Childs.Clear;
if FSysInfos then
QNames.SQL.Text := QRYSysDomains
else
QNames.SQL.Text := QRYDomains;
QNames.Open;
while not QNames.Eof do
begin
with TMetaDomain.Create(Self, Ord(OIDDomain)) do
LoadFromQuery(QNames, QCharset);
QNames.Next;
end;
end;
// GENERATORS
if OIDGenerator in FOIDDatabases then
begin
FNodeItems[Ord(OIDGenerator)].Childs.Clear;
QNames.SQL.Text := QRYGenerators;
QNames.Open;
while not QNames.Eof do
begin
with TMetaGenerator.Create(Self, Ord(OIDGenerator)) do
LoadFromDataBase(Transaction, Trim(QNames.Fields.AsString[0]));
QNames.Next;
end;
end;
// TABLES
if OIDTable in FOIDDatabases then
begin
FNodeItems[Ord(OIDTable)].Childs.Clear;
if FSysInfos then
QNames.SQL.Text := QRYSysTables
else
QNames.SQL.Text := QRYTables;
QNames.Open;
while not QNames.Eof do
begin
with TMetaTable.Create(Self, Ord(OIDTable)) do
LoadFromDataBase(QNames, QFields, QCharset, QPrimary,
QIndex, QForeign, QCheck, QTrigger, FOIDTables);
QNames.Next;
end;
// FOREIGN
if [OIDForeign, OIDTableField] <= FOIDTables then
begin
for I := 0 to TablesCount - 1 do
begin
QForeign.Params.AsString[0] := Tables[I].Name;
QForeign.Open;
ConStr := '';
while not QForeign.Eof do
begin
if ConStr <> Trim(QForeign.Fields.AsString[0]) then // new
begin
with TMetaForeign.Create(Tables[I], Ord(OIDForeign)) do
begin
FName := Trim(QForeign.Fields.AsString[0]);
ConStr := FName;
FForTable := FindTableIndex(Trim(QForeign.Fields.AsString[3]));
if 'TABLE1' = Trim(QForeign.Fields.AsString[3]) then
beep;
SetLength(FFields, 1);
FFields[0] := Tables[I].FindFieldIndex(Trim(QForeign.Fields.AsString[5]));
Include(Tables[I].Fields[FFields[0]].FInfos, fForeign);
SetLength(FForFields, 1);
FForFields[0] := ForTable.FindFieldIndex(Trim(QForeign.Fields.AsString[4]));
Str := Trim(QForeign.Fields.AsString[1]);
if Str = 'RESTRICT' then
FOnUpdate := Restrict
else
if Str = 'CASCADE' then
FOnUpdate := Cascade
else
if Str = 'SET NULL' then
FOnUpdate := SetNull
else
FOnUpdate := SetDefault;
Str := Trim(QForeign.Fields.AsString[2]);
if Str = 'RESTRICT' then
FOnDelete := Restrict
else
if Str = 'CASCADE' then
FOnDelete := Cascade
else
if Str = 'SET NULL' then
FOnDelete := SetNull
else
FOnDelete := SetDefault;
end;
end
else
with Tables[I].Foreign[Tables[I].ForeignCount - 1] do
begin
SetLength(FFields, Length(FFields) + 1);
FFields[FieldsCount - 1] := Tables[I].FindFieldIndex(Trim(QForeign.Fields.AsString[5]));
Include(Tables[I].Fields[FFields[FieldsCount - 1]].FInfos, fForeign);
SetLength(FForFields, Length(FForFields) + 1);
FForFields[ForFieldsCount - 1] := ForTable.FindFieldIndex(Trim(QForeign.Fields.AsString[4]));
end;
QForeign.Next;
end;
end;
end;
end;
// VIEWS
if OIDView in FOIDDatabases then
begin
FNodeItems[Ord(OIDView)].Childs.Clear;
QNames.SQL.Text := QRYView;
QNames.Open;
while not QNames.Eof do
begin
with TMetaView.Create(Self, Ord(OIDView)) do
LoadFromDataBase(QNames, QFields, QTrigger, QCharset, FOIDViews);
QNames.Next;
end;
end;
// PROCEDURE
if OIDProcedure in FOIDDatabases then
begin
FNodeItems[Ord(OIDProcedure)].Childs.Clear;
QNames.SQL.Text := QRYProcedures;
QFields.SQL.Text := QRYProcFields;
QNames.Open;
while not QNames.Eof do
begin
with TMetaProcedure.Create(Self, Ord(OIDProcedure)) do
LoadFromQuery(QNames, QFields, QCharset, FOIDProcedures);
QNames.Next;
end;
end;
// EXCEPTION
if OIDException in FOIDDatabases then
begin
FNodeItems[Ord(OIDException)].Childs.Clear;
QNames.SQL.Text := QRYExceptions;
QNames.Open;
while not QNames.Eof do
begin
TMetaException.Create(Self, Ord(OIDException)).LoadFromQuery(QNames);
QNames.Next;
end;
end;
// UDF
if OIDUDF in FOIDDatabases then
begin
FNodeItems[Ord(OIDUDF)].Childs.Clear;
QNames.SQL.Text := QRYUDF;
QFields.SQL.Text := QRYUDFFields;
QNames.Open;
while not QNames.Eof do
begin
TMetaUDF.Create(Self, Ord(OIDUDF)).LoadFromQuery(QNames, QFields, QCharset, FOIDUDFs);
QNames.Next;
end;
end;
// ROLES
if OIDRole in FOIDDatabases then
begin
FNodeItems[Ord(OIDRole)].Childs.Clear;
QNames.SQL.Text := QRYRoles;
QNames.Open;
while not QNames.Eof do
begin
TMetaRole.Create(Self, Ord(OIDRole)).LoadFromQuery(QNames);
QNames.Next;
end;
end;
finally
QNames.Free;
QCharset.Free;
QFields.Free;
QPrimary.Free;
QIndex.Free;
QForeign.Free;
QCheck.Free;
QTrigger.Free;
end;
end;
procedure TMetaDataBase.SaveToDDL(Stream: TStringStream);
var
I: Integer;
procedure SaveChildNodes(comment: string; OIDParent, OIDChild: Integer;
Separator: string = BreakLine);
var
I, J: Integer;
begin
if TablesCount > 0 then
begin
Stream.WriteString(NewLine);
Stream.WriteString(Format('/* %s */', [comment]));
Stream.WriteString(BreakLine);
for I := 0 to FNodeItems[OIDParent].Childs.Count - 1 do
for J := 0 to GetItems(OIDParent, I).FNodeItems[OIDChild].Childs.Count - 1 do
begin
Stream.WriteString(Separator);
TMetaNode(GetItems(OIDParent, I).FNodeItems[OIDChild].Childs[J]).SaveToDDL(Stream);
end;
end;
end;
procedure SaveMainNodes(Comment: string; OID: Integer;
Separator: string = NewLine);
var
I: Integer;
begin
if FNodeItems[OID].Childs.Count > 0 then
begin
Stream.WriteString(NewLine);
Stream.WriteString(Format('/* %s */', [comment]));
for I := 0 to FNodeItems[OID].Childs.Count - 1 do
begin
if I = 0 then
Stream.WriteString(NewLine)
else
Stream.WriteString(Separator);
if GetItems(OID, I) is TMetaProcedure then
TMetaProcedure(GetItems(OID, I)).SaveToPostDDL(Stream)
else
GetItems(OID, I).SaveToDDLNode(Stream);
end;
end;
end;
begin
SaveMainNodes('ROLES', Ord(OIDRole), NewLine);
SaveMainNodes('FUNCTIONS', Ord(OIDUDF), NewLine);
SaveMainNodes('DOMAINS', Ord(OIDDomain), BreakLine);
SaveMainNodes('GENERATORS', Ord(OIDGenerator));
SaveMainNodes('EXEPTIONS', Ord(OIDException), BreakLine);
SaveMainNodes('PROCEDURES', Ord(OIDProcedure));
SaveMainNodes('TABLES', Ord(OIDTable));
SaveMainNodes('VIEWS', Ord(OIDView));
SaveChildNodes('UNIQUE', Ord(OIDTable), Ord(OIDUnique));
SaveChildNodes('PRIMARY', Ord(OIDTable), Ord(OIDPrimary));
SaveChildNodes('FOREIGN', Ord(OIDTable), Ord(OIDForeign));
SaveChildNodes('INDICES', Ord(OIDTable), Ord(OIDIndex));
SaveChildNodes('CHECKS', Ord(OIDTable), Ord(OIDCheck), NewLine);
SaveChildNodes('TRIGGERS', Ord(OIDTable), Ord(OIDTableTrigger), NewLine);
SaveChildNodes('TRIGGERS (Views)', Ord(OIDView), Ord(OIDViewTrigers), NewLine);
if ProceduresCount > 0 then
begin
Stream.WriteString(NewLine);
Stream.WriteString('/* PROCEDURES */');
for I := 0 to ProceduresCount - 1 do
begin
Stream.WriteString(NewLine);
Procedures[I].SaveToAlterDDL(Stream);
end;
end;
end;
function TMetaDataBase.GetGenerators(const Index: Integer): TMetaGenerator;
begin
Result := TMetaGenerator(GetItems(Ord(OIDGenerator), Index));
end;
function TMetaDataBase.GetGeneratorsCount: Integer;
begin
Result := FNodeItems[Ord(OIDGenerator)].Childs.Count
end;
function TMetaDataBase.GetTables(const Index: Integer): TMetaTable;
begin
Result := TMetaTable(GetItems(Ord(OIDTable), Index));
end;
function TMetaDataBase.GetTablesCount: Integer;
begin
Result := FNodeItems[Ord(OIDTable)].Childs.Count
end;
function TMetaDataBase.FindTableName(const TableName: string): TMetaTable;
var
I: Integer;
begin
Result := nil;
for I := 0 to TablesCount - 1 do
if Tables[I].Name = TableName then
begin
Result := Tables[I];
Exit;
end;
end;
function TMetaDataBase.FindTableIndex(const TableName: string): Integer;
begin
for Result := 0 to TablesCount - 1 do
if Tables[Result].Name = TableName then
Exit;
raise Exception.CreateFmt(EUIB_TABLESTRNOTFOUND, [TableName]);
end;
function TMetaDataBase.FindDomainIndex(const DomainName: string): Integer;
begin
for Result := 0 to DomainsCount - 1 do
if Domains[Result].Name = DomainName then
Exit;
raise Exception.CreateFmt(EUIB_DOMAINSTRNOTFOUND, [DomainName]);
end;
procedure TMetaDataBase.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
end;
function TMetaDataBase.GetViews(const Index: Integer): TMetaView;
begin
Result := TMetaView(GetItems(Ord(OIDView), Index));
end;
function TMetaDataBase.GetViewsCount: Integer;
begin
Result := FNodeItems[Ord(OIDView)].Childs.Count
end;
function TMetaDataBase.GetDomains(const Index: Integer): TMetaDomain;
begin
Result := TMetaDomain(GetItems(Ord(OIDDomain), Index));
end;
function TMetaDataBase.GetDomainsCount: Integer;
begin
Result := FNodeItems[Ord(OIDDomain)].Childs.Count
end;
function TMetaDataBase.GetProcedures(const Index: Integer): TMetaProcedure;
begin
Result := TMetaProcedure(GetItems(Ord(OIDProcedure), Index));
end;
function TMetaDataBase.GetProceduresCount: Integer;
begin
Result := FNodeItems[Ord(OIDProcedure)].Childs.Count
end;
function TMetaDataBase.GetExceptions(const Index: Integer): TMetaException;
begin
Result := TMetaException(GetItems(Ord(OIDException), Index));
end;
function TMetaDataBase.GetExceptionsCount: Integer;
begin
Result := FNodeItems[Ord(OIDException)].Childs.Count
end;
function TMetaDataBase.GetUDFS(const Index: Integer): TMetaUDF;
begin
Result := TMetaUDF(GetItems(Ord(OIDUDF), Index));
end;
function TMetaDataBase.GetUDFSCount: Integer;
begin
Result := FNodeItems[Ord(OIDUDF)].Childs.Count
end;
class function TMetaDataBase.NodeClass: string;
begin
Result := 'Database';
end;
procedure TMetaDataBase.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
inherited SaveToStream(Stream);
end;
function TMetaDataBase.GetRoles(const Index: Integer): TMetaRole;
begin
Result := TMetaRole(GetItems(Ord(OIDRole), Index));
end;
function TMetaDataBase.GetRolesCount: Integer;
begin
Result := FNodeItems[Ord(OIDRole)].Childs.Count
end;
class function TMetaDataBase.NodeType: TMetaNodeType;
begin
Result := MetaDatabase;
end;
function TMetaDataBase.FindProcName(const ProcName: string): TMetaProcedure;
var
I: Integer;
begin
for I := 0 to ProceduresCount - 1 do
if Procedures[I].Name = ProcName then
begin
Result := Procedures[I];
Exit;
end;
raise Exception.CreateFmt(EUIB_PROCSTRNOTFOUND, [ProcName]);
end;
//=== { TMetaConstraint } ====================================================
function TMetaConstraint.GetFields(const Index: Word): TMetaTableField;
begin
Assert((FieldsCount > 0) and (Index < FieldsCount), IntToStr(Index) + ' ' + ClassName);
Result := TMetaTable(FOwner).Fields[FFields[Index]];
end;
function TMetaConstraint.GetFieldsCount: Word;
begin
Result := Length(FFields);
end;
class function TMetaConstraint.NodeClass: string;
begin
Result := 'Constraint'
end;
procedure TMetaConstraint.LoadFromStream(Stream: TStream);
var
I: Integer;
begin
Stream.Read(I, SizeOf(I));
SetLength(FFields, I);
if I > 0 then
begin
ReadString(Stream, FName);
for I := 0 to I - 1 do
begin
Stream.Read(FFields[I], SizeOf(FFields[I]));
case NodeType of
MetaForeign:
Include(TMetaTable(FOwner).Fields[FFields[I]].FInfos, fForeign);
MetaIndex:
Include(TMetaTable(FOwner).Fields[FFields[I]].FInfos, fIndice);
MetaPrimary:
Include(TMetaTable(FOwner).Fields[FFields[I]].FInfos, fPrimary);
MetaUnique:
Include(TMetaTable(FOwner).Fields[FFields[I]].FInfos, fPrimary);
end;
end;
end;
end;
procedure TMetaConstraint.SaveToStream(Stream: TStream);
var
I: Integer;
begin
I := FieldsCount;
Stream.Write(I, SizeOf(I));
if I > 0 then
begin
WriteString(Stream, FName);
for I := 0 to I - 1 do
Stream.Write(FFields[I], SizeOf(FFields[I]));
end;
end;
class function TMetaConstraint.NodeType: TMetaNodeType;
begin
Result := MetaConstraint;
end;
//=== { TMetaUnique } ========================================================
class function TMetaUnique.NodeClass: string;
begin
Result := 'Unique';
end;
class function TMetaUnique.NodeType: TMetaNodeType;
begin
Result := MetaUnique;
end;
procedure TMetaUnique.SaveToDDL(Stream: TStringStream);
var
I: Integer;
begin
Stream.WriteString(Format('ALTER TABLE %s ADD UNIQUE (',
[TMetaTable(FOwner).FName]));
for I := 0 to FieldsCount - 1 do
begin
Stream.WriteString(Fields[I].Name);
if I <> FieldsCount - 1 then
Stream.WriteString(', ');
end;
Stream.WriteString(');');
end;
//=== { TMetaPrimary } =======================================================
class function TMetaPrimary.NodeClass: string;
begin
Result := 'Primary key';
end;
procedure TMetaPrimary.LoadFromQuery(Q: TJvUIBStatement);
var
I: Integer;
begin
FName := Trim(Q.Fields.AsString[0]);
Q.FetchAll;
SetLength(FFields, Q.Fields.RecordCount);
for I := 0 to Q.Fields.RecordCount - 1 do
begin
Q.Fields.GetRecord(I);
FFields[I] := TMetaTable(FOwner).FindFieldIndex(Trim(Q.Fields.AsString[1]));
Include(TMetaTable(FOwner).Fields[FFields[I]].FInfos, fPrimary);
end;
end;
procedure TMetaPrimary.SaveToDDLNode(Stream: TStringStream);
var
I: Integer;
begin
if copy(FName, 0, 6) = 'INTEG_' then
Stream.WriteString(Format('ALTER TABLE %s ADD PRIMARY KEY (',
[TMetaTable(FOwner).FName]))
else
Stream.WriteString(Format('ALTER TABLE %s ADD CONSTRAINT %s PRIMARY KEY (',
[TMetaTable(FOwner).FName, FName]));
for I := 0 to FieldsCount - 1 do
begin
Stream.WriteString(Fields[I].Name);
if I <> FieldsCount - 1 then
Stream.WriteString(', ');
end;
Stream.WriteString(');');
end;
class function TMetaPrimary.NodeType: TMetaNodeType;
begin
Result := MetaPrimary;
end;
//=== { TMetaIndex } =========================================================
class function TMetaIndex.NodeClass: string;
begin
// (rom) better Indices or Index?
Result := 'Indice';
end;
procedure TMetaIndex.LoadFromStream(Stream: TStream);
begin
inherited LoadFromStream(Stream);
Stream.Read(FUnique, SizeOf(FUnique));
Stream.Read(FActive, SizeOf(FActive));
Stream.Read(FOrder, SizeOf(FOrder));
end;
procedure TMetaIndex.SaveToDDLNode(Stream: TStringStream);
var
I: Integer;
UNIQUE, ORDER: string;
begin
if FUnique then
UNIQUE := ' UNIQUE';
if FOrder = IoDescending then
ORDER := ' DESCENDING';
Stream.WriteString(Format('CREATE%s%s INDEX %s ON %s (',
[ORDER, UNIQUE, FName, TMetaTable(FOwner).FName]));
for I := 0 to FieldsCount - 1 do
begin
Stream.WriteString(Fields[I].Name);
if I <> FieldsCount - 1 then
Stream.WriteString(', ');
end;
Stream.WriteString(');');
if not FActive then
Stream.WriteString(Format('%sALTER INDEX %s INACTIVE;', [BreakLine, FName]));
end;
procedure TMetaIndex.SaveToStream(Stream: TStream);
begin
inherited SaveToStream(Stream);
Stream.Write(FUnique, SizeOf(FUnique));
Stream.Write(FActive, SizeOf(FActive));
Stream.Write(FOrder, SizeOf(FOrder));
end;
class function TMetaIndex.NodeType: TMetaNodeType;
begin
Result := MetaIndex;
end;
//=== { TMetaForeign } =======================================================
function TMetaForeign.GetForFields(const Index: Word): TMetaTableField;
begin
Assert((ForFieldsCount > 0) and (Index < ForFieldsCount));
Result := ForTable.Fields[FForFields[Index]];
end;
function TMetaForeign.GetForFieldsCount: Word;
begin
Result := Length(FForFields);
end;
function TMetaForeign.GetForTable: TMetaTable;
begin
Result := TMetaDataBase(FOwner.FOwner).Tables[FForTable];
end;
class function TMetaForeign.NodeClass: string;
begin
Result := 'Foreign';
end;
procedure TMetaForeign.LoadFromStream(Stream: TStream);
var
I: Integer;
begin
inherited LoadFromStream(Stream);
Stream.Read(FForTable, SizeOf(FForTable));
Stream.Read(FOnDelete, SizeOf(FOnDelete));
Stream.Read(FOnUpdate, SizeOf(FOnUpdate));
Stream.Read(I, SizeOf(I));
SetLength(FForFields, I);
for I := 0 to I - 1 do
Stream.Read(FForFields[I], SizeOf(FForFields[I]));
end;
procedure TMetaForeign.SaveToDDLNode(Stream: TStringStream);
var
I: Integer;
begin
if copy(FName, 0, 6) = 'INTEG_' then
Stream.WriteString(Format('ALTER TABLE %s ADD FOREIGN KEY (',
[TMetaTable(FOwner).FName]))
else
Stream.WriteString(Format('ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (',
[TMetaTable(FOwner).FName, FName]));
for I := 0 to FieldsCount - 1 do
begin
Stream.WriteString(Fields[I].Name);
if I <> FieldsCount - 1 then
Stream.WriteString(', ');
end;
Stream.WriteString(Format(') REFERENCES %s (', [ForTable.Name]));
for I := 0 to ForFieldsCount - 1 do
begin
Stream.WriteString(ForFields[I].Name);
if I <> ForFieldsCount - 1 then
Stream.WriteString(', ');
end;
Stream.WriteString(')');
case OnDelete of
Cascade:
Stream.WriteString(' ON DELETE CASCADE');
SetNull:
Stream.WriteString(' ON DELETE SET NULL');
SetDefault:
Stream.WriteString(' ON DELETE SET DEFAULT');
end;
case OnUpdate of
Cascade:
Stream.WriteString(' ON UPDATE CASCADE');
SetNull:
Stream.WriteString(' ON UPDATE SET NULL');
SetDefault:
Stream.WriteString(' ON UPDATE SET DEFAULT');
end;
Stream.WriteString(';');
end;
procedure TMetaForeign.SaveToStream(Stream: TStream);
var
I: Integer;
begin
inherited SaveToStream(Stream);
Stream.Write(FForTable, SizeOf(FForTable));
Stream.Write(FOnDelete, SizeOf(FOnDelete));
Stream.Write(FOnUpdate, SizeOf(FOnUpdate));
I := ForFieldsCount;
Stream.Write(I, SizeOf(I));
for I := 0 to I - 1 do
Stream.Write(FForFields[I], SizeOf(FForFields[I]));
end;
class function TMetaForeign.NodeType: TMetaNodeType;
begin
Result := MetaForeign;
end;
//=== { TMetaCheck } =========================================================
class function TMetaCheck.NodeClass: string;
begin
Result := 'Check';
end;
procedure TMetaCheck.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
ReadString(Stream, FConstraint);
end;
procedure TMetaCheck.SaveToDDLNode(Stream: TStringStream);
begin
Stream.WriteString(Format('ALTER TABLE %s ADD %s;',
[TMetaTable(FOwner).Name, FConstraint]));
end;
procedure TMetaCheck.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
WriteString(Stream, FConstraint);
end;
class function TMetaCheck.NodeType: TMetaNodeType;
begin
Result := MetaCheck;
end;
//=== { TMetaTrigger } =======================================================
class function TMetaTrigger.DecodePrefix(Value: Integer): TTriggerPrefix;
begin
Result := TTriggerPrefix((Value + 1) and 1);
end;
class function TMetaTrigger.DecodeSuffixes(Value: Integer): TTriggerSuffixes;
var
V, Slot: Integer;
begin
Result := [];
for Slot := 1 to 3 do
begin
V := ((Value + 1) shr (Slot * 2 - 1)) and 3;
if V > 0 then
Include(Result, TTriggerSuffix(V - 1));
end;
end;
class function TMetaTrigger.NodeClass: string;
begin
Result := 'Trigger';
end;
procedure TMetaTrigger.LoadFromQuery(Q: TJvUIBStatement);
begin
FName := Trim(Q.Fields.AsString[0]);
Q.ReadBlob(1, FSource);
FPosition := Q.Fields.AsSmallint[2];
FPrefix := DecodePrefix(Q.Fields.AsSmallint[3]);
FSuffix := DecodeSuffixes(Q.Fields.AsSmallint[3]);
FActive := Q.Fields.AsSmallint[4] = 0;
end;
procedure TMetaTrigger.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
Stream.Read(FPrefix, SizeOf(FPrefix));
Stream.Read(FSuffix, SizeOf(FSuffix));
Stream.Read(FPosition, SizeOf(FPosition));
Stream.Read(FActive, SizeOf(FActive));
ReadString(Stream, FSource);
end;
procedure TMetaTrigger.SaveToDDLNode(Stream: TStringStream);
var
Count: Smallint;
Suf: TTriggerSuffix;
begin
Stream.WriteString(Format('CREATE TRIGGER %s FOR %s%s',
[Name, TMetaNode(FOwner).Name, BreakLine]));
if FActive then
Stream.WriteString('ACTIVE ');
Stream.WriteString(TriggerPrefixTypes[FPrefix] + ' ');
Count := 0;
for Suf := Insert to Delete do
if Suf in FSuffix then
begin
Inc(Count);
if Count > 1 then
Stream.WriteString(' OR ');
Stream.WriteString(TriggerSuffixTypes[Suf]);
end;
Stream.WriteString(Format(' POSITION %d%s%s;', [FPosition, BreakLine, FSource]));
end;
procedure TMetaTrigger.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
Stream.Write(FPrefix, SizeOf(FPrefix));
Stream.Write(FSuffix, SizeOf(FSuffix));
Stream.Write(FPosition, SizeOf(FPosition));
Stream.Write(FActive, SizeOf(FActive));
WriteString(Stream, FSource);
end;
class function TMetaTrigger.NodeType: TMetaNodeType;
begin
Result := MetaTrigger;
end;
//=== { TMetaView } ==========================================================
constructor TMetaView.Create(AOwner: TMetaNode; ClassIndex: Integer);
begin
inherited Create(AOwner, ClassIndex);
AddClass(TMetaField);
AddClass(TMetaTrigger);
end;
function TMetaView.GetFields(const Index: Integer): TMetaField;
begin
Result := TMetaField(GetItems(Ord(OIDViewFields), Index))
end;
function TMetaView.GetFieldsCount: Integer;
begin
Result := FNodeItems[Ord(OIDViewFields)].Childs.Count;
end;
class function TMetaView.NodeClass: string;
begin
Result := 'View';
end;
function TMetaView.GetTriggers(const Index: Integer): TMetaTrigger;
begin
Result := TMetaTrigger(GetItems(Ord(OIDViewTrigers), Index))
end;
function TMetaView.GetTriggersCount: Integer;
begin
Result := FNodeItems[Ord(OIDViewTrigers)].Childs.Count;
end;
procedure TMetaView.LoadFromDataBase(QName, QFields, QTriggers,
QCharset: TJvUIBStatement; OIDs: TOIDViews);
begin
FName := Trim(QName.Fields.AsString[0]);
QName.ReadBlob(1, FSource);
FSource := Trim(FSource);
// FIELD
if OIDViewFields in OIDs then
begin
QFields.Params.AsString[0] := FName;
QFields.Open;
while not QFields.Eof do
begin
TMetaField.Create(Self, Ord(OIDViewFields)).LoadFromQuery(QFields, QCharset);
QFields.Next;
end;
end;
// TRIGGER
if OIDViewTrigers in OIDs then
begin
QTriggers.Params.AsString[0] := FName;
QTriggers.Open;
while not QTriggers.Eof do
begin
TMetaTrigger.Create(Self, Ord(OIDViewTrigers)).LoadFromQuery(QTriggers);
QTriggers.Next;
end;
end;
end;
procedure TMetaView.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
ReadString(Stream, FSource);
end;
procedure TMetaView.SaveToDDL(Stream: TStringStream);
begin
inherited SaveToDDL(Stream);
SaveNode(Stream, Ord(OIDViewTrigers), NewLine);
end;
procedure TMetaView.SaveToDDLNode(Stream: TStringStream);
var
I: Integer;
begin
Stream.WriteString(Format('CREATE VIEW %s (', [Name]));
for I := 0 to FieldsCount - 1 do
begin
Stream.WriteString(BreakLine + ' ' + Fields[I].Name);
if I <> FieldsCount - 1 then
Stream.WriteString(',');
end;
Stream.WriteString(BreakLine + ')' + BreakLine + 'AS' + BreakLine);
Stream.WriteString(Source);
Stream.WriteString(';');
end;
procedure TMetaView.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
WriteString(Stream, FSource);
inherited SaveToStream(Stream);
end;
class function TMetaView.NodeType: TMetaNodeType;
begin
Result := MetaView;
end;
//=== { TMetaDomain } ========================================================
class function TMetaDomain.NodeClass: string;
begin
Result := 'Domain';
end;
class function TMetaDomain.NodeType: TMetaNodeType;
begin
Result := MetaDomain;
end;
procedure TMetaDomain.SaveToDDL(Stream: TStringStream);
begin
SaveToDDLNode(Stream);
end;
procedure TMetaDomain.SaveToDDLNode(Stream: TStringStream);
begin
Stream.WriteString(Format('CREATE DOMAIN %s AS ', [FName]));
inherited SaveToDDLNode(Stream);
Stream.WriteString(';');
end;
//=== { TMetaProcedure } =====================================================
constructor TMetaProcedure.Create(AOwner: TMetaNode; ClassIndex: Integer);
begin
inherited Create(AOwner, ClassIndex);
AddClass(TMetaProcInField); // in
AddClass(TMetaProcOutField); // out
end;
function TMetaProcedure.GetInputFields(const Index: Integer): TMetaProcInField;
begin
Result := TMetaProcInField(GetItems(Ord(OIDProcFieldIn), Index))
end;
function TMetaProcedure.GetInputFieldsCount: Integer;
begin
Result := FNodeItems[Ord(OIDProcFieldIn)].Childs.Count;
end;
class function TMetaProcedure.NodeClass: string;
begin
Result := 'Procedure';
end;
function TMetaProcedure.GetOutputFields(const Index: Integer): TMetaProcOutField;
begin
Result := TMetaProcOutField(GetItems(Ord(OIDProcFieldOut), Index))
end;
function TMetaProcedure.GetOutputFieldsCount: Integer;
begin
Result := FNodeItems[Ord(OIDProcFieldOut)].Childs.Count;
end;
procedure TMetaProcedure.InternalSaveToDDL(Stream: TStringStream;
Operation: string);
var
I: Integer;
begin
Stream.WriteString(Format('%s PROCEDURE %s', [Operation, FName]));
if InputFieldsCount > 0 then
begin
Stream.WriteString(' (');
for I := 0 to InPutFieldsCount - 1 do
begin
Stream.WriteString(BreakLine + ' ');
InputFields[I].SaveToDDL(Stream);
if I <> InputFieldsCount - 1 then
Stream.WriteString(',');
end;
Stream.WriteString(')');
end;
if OutputFieldsCount > 0 then
begin
Stream.WriteString(Format('%sRETURNS (', [BreakLine]));
for I := 0 to OutputFieldsCount - 1 do
begin
Stream.WriteString(BreakLine + ' ');
OutputFields[I].SaveToDDL(Stream);
if I <> OutputFieldsCount - 1 then
Stream.WriteString(',');
end;
Stream.WriteString(')');
end;
end;
procedure TMetaProcedure.LoadFromQuery(QNames, QFields,
QCharset: TJvUIBStatement; OIDs: TOIDProcedures);
begin
FName := Trim(QNames.Fields.AsString[0]);
QNames.ReadBlob(1, FSource);
QFields.Params.AsString[0] := FName;
if OIDProcFieldIn in OIDs then
begin
QFields.Params.AsSmallint[1] := 0; // in
QFields.Open;
while not QFields.Eof do
begin
TMetaProcInField.Create(Self, Ord(OIDProcFieldIn)).LoadFromQuery(QFields, QCharset);
QFields.Next;
end;
end;
if OIDProcFieldOut in OIDs then
begin
QFields.Params.AsSmallint[1] := 1; // out
QFields.Open;
while not QFields.Eof do
begin
TMetaProcOutField.Create(Self, Ord(OIDProcFieldOut)).LoadFromQuery(QFields, QCharset);
QFields.Next;
end;
end;
end;
procedure TMetaProcedure.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
ReadString(Stream, FSource);
end;
procedure TMetaProcedure.SaveToAlterDDL(Stream: TStringStream);
begin
InternalSaveToDDL(Stream, 'ALTER');
Stream.WriteString(BreakLine + 'AS');
Stream.WriteString(FSource);
Stream.WriteString(';');
end;
procedure TMetaProcedure.SaveToPostDDL(Stream: TStringStream);
begin
InternalSaveToDDL(Stream, 'CREATE');
Stream.WriteString(BreakLine + 'AS' + breakline + 'BEGIN' + breakline +
' EXIT;' + breakline + 'END;');
end;
procedure TMetaProcedure.SaveToDDLNode(Stream: TStringStream);
begin
InternalSaveToDDL(Stream, 'CREATE');
Stream.WriteString(BreakLine + 'AS');
Stream.WriteString(FSource);
Stream.WriteString(';');
end;
procedure TMetaProcedure.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
WriteString(Stream, FSource);
inherited SaveToStream(Stream);
end;
class function TMetaProcedure.NodeType: TMetaNodeType;
begin
Result := MetaProcedure;
end;
//=== { TMetaException } =====================================================
class function TMetaException.NodeClass: string;
begin
Result := 'Exception';
end;
procedure TMetaException.LoadFromQuery(QName: TJvUIBStatement);
begin
FName := Trim(QName.Fields.AsString[0]);
FMessage := QName.Fields.AsString[1];
FNumber := QName.Fields.AsInteger[2];
end;
procedure TMetaException.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
ReadString(Stream, FMessage);
Stream.Read(FNumber, SizeOf(FNumber))
end;
procedure TMetaException.SaveToDDLNode(Stream: TStringStream);
begin
Stream.WriteString(Format('CREATE EXCEPTION %s ''%s'';', [FName, FMessage]));
end;
procedure TMetaException.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
WriteString(Stream, FMessage);
Stream.Write(FNumber, SizeOf(FNumber));
inherited SaveToStream(Stream);
end;
class function TMetaException.NodeType: TMetaNodeType;
begin
Result := MetaException;
end;
//=== { TMetaUDF } ===========================================================
constructor TMetaUDF.Create(AOwner: TMetaNode; ClassIndex: Integer);
begin
inherited Create(AOwner, ClassIndex);
AddClass(TMetaUDFField);
end;
class function TMetaUDF.NodeClass: string;
begin
Result := 'UDF';
end;
procedure TMetaUDF.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
ReadString(Stream, FModule);
ReadString(Stream, FEntry);
Stream.Read(FReturn, SizeOf(FReturn));
end;
procedure TMetaUDF.SaveToDDLNode(Stream: TStringStream);
var
I, C: Integer;
begin
Stream.WriteString(Format('DECLARE EXTERNAL FUNCTION %s', [Fname]));
C := 0;
if FReturn = 0 then
begin // return position
for I := 0 to FieldsCount - 1 do
if Fields[I].Position <> Return then
begin
if C > 0 then
Stream.WriteString(',');
Stream.WriteString(BreakLine + ' ');
Fields[I].SaveToDDL(Stream);
Inc(C);
end;
for I := 0 to FieldsCount - 1 do
if Fields[I].Position = Return then
begin
Stream.WriteString(BreakLine + ' RETURNS ');
Fields[I].SaveToDDL(Stream);
Break;
end;
end
else
begin
for I := 0 to FieldsCount - 1 do
begin
if C > 0 then
Stream.WriteString(',');
Stream.WriteString(BreakLine + ' ');
Fields[I].SaveToDDL(Stream);
Inc(C);
end;
Stream.WriteString(Format('%s RETURNS PARAMETER %d', [BreakLine, Freturn]));
end;
Stream.WriteString(Format('%s ENTRY_POINT ''%s'' MODULE_NAME ''%s'';',
[BreakLine, FEntry, FModule]));
end;
procedure TMetaUDF.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
WriteString(Stream, FModule);
WriteString(Stream, FEntry);
Stream.Write(FReturn, SizeOf(FReturn));
inherited SaveToStream(Stream);
end;
procedure TMetaUDF.LoadFromQuery(QNames, QFields, QCharset: TJvUIBStatement; OIDs: TOIDUDFs);
begin
FName := Trim(QNames.Fields.AsString[0]);
FModule := QNames.Fields.AsString[1];
FEntry := Trim(QNames.Fields.AsString[2]);
FReturn := QNames.Fields.AsSmallint[3];
if OIDUDFField in OIDs then
begin
QFields.Params.AsString[0] := FName;
QFields.Open;
while not QFields.Eof do
begin
TMetaUDFField.Create(Self, Ord(OIDUDFField)).LoadFromQuery(QFields, QCharset);
QFields.Next;
end;
end;
end;
function TMetaUDF.GetFields(const Index: Integer): TMetaUDFField;
begin
Result := TMetaUDFField(GetItems(Ord(OIDUDFField), Index))
end;
function TMetaUDF.GetFieldsCount: Integer;
begin
Result := FNodeItems[Ord(OIDUDFField)].Childs.Count;
end;
class function TMetaUDF.NodeType: TMetaNodeType;
begin
Result := MetaUDF;
end;
//=== { TMetaTableField } ====================================================
function TMetaTableField.GetDomain: TMetaDomain;
begin
if FDomain >= 0 then
Result := TMetaDatabase(FOwner.FOwner).Domains[FDomain]
else
Result := nil;
end;
procedure TMetaTableField.LoadFromQuery(Q, C: TJvUIBStatement);
begin
inherited LoadFromQuery(Q, C);
FNotNull := (Q.Fields.AsSmallint[8] = 1);
if not Q.Fields.IsNull[9] then
begin
Q.ReadBlob(9, FDefaultValue);
FDefaultValue := Trim(FDefaultValue);
if FDefaultValue <> '' then
FDefaultValue := Copy(FDefaultValue, 9,
System.Length(FDefaultValue) - 8);
end
else
FDefaultValue := '';
FDomain := -1;
if not (Self is TMetaDomain) then
begin
if OIDDomain in TMetaDataBase(FOwner.FOwner).FOIDDatabases then
if not (Q.Fields.IsNull[10] or (Copy(Q.Fields.AsString[10], 1, 4) = 'RDB$')) then
FDomain :=
TMetaDataBase(FOwner.FOwner).FindDomainIndex(Trim(Q.Fields.AsString[10]));
Q.ReadBlob(11, FComputedSource);
end;
end;
procedure TMetaTableField.LoadFromStream(Stream: TStream);
begin
inherited LoadFromStream(Stream);
ReadString(Stream, FDefaultValue);
Stream.Read(FNotNull, SizeOf(FNotNull));
Stream.Read(FDomain, SizeOf(FDomain));
ReadString(Stream, FComputedSource);
end;
class function TMetaTableField.NodeType: TMetaNodeType;
begin
Result := MetaTableField;
end;
procedure TMetaTableField.SaveToDDLNode(Stream: TStringStream);
begin
if FDomain >= 0 then
Stream.WriteString(Domain.Name) else
if FComputedSource <> '' then
Stream.WriteString('COMPUTED BY ' + FComputedSource) else
inherited SaveToDDLNode(Stream);
if FDefaultValue <> '' then
Stream.WriteString(' DEFAULT ' + FDefaultValue);
if FNotNull then
Stream.WriteString(' NOT NULL');
end;
procedure TMetaTableField.SaveToStream(Stream: TStream);
begin
inherited SaveToStream(Stream);
WriteString(Stream, FDefaultValue);
Stream.Write(FNotNull, SizeOf(FNotNull));
Stream.Write(FDomain, SizeOf(FDomain));
WriteString(Stream, FComputedSource);
end;
//=== { TMetaProcInField } ===================================================
class function TMetaProcInField.NodeClass: string;
begin
Result := 'Input parameter';
end;
class function TMetaProcInField.NodeType: TMetaNodeType;
begin
Result := MetaProcInField;
end;
//=== { TMetaProcOutField } ==================================================
class function TMetaProcOutField.NodeClass: string;
begin
Result := 'Output parameter';
end;
class function TMetaProcOutField.NodeType: TMetaNodeType;
begin
Result := MetaProcOutField;
end;
//=== { TMetaField } =========================================================
procedure TMetaField.LoadFromQuery(Q, C: TJvUIBStatement);
begin
inherited LoadFromQuery(Q, C);
FName := Trim(Q.Fields.AsString[6]);
FSegmentLength := Q.Fields.AsSmallint[7];
end;
class function TMetaField.NodeType: TMetaNodeType;
begin
Result := MetaField;
end;
procedure TMetaField.SaveToDDL(Stream: TStringStream);
begin
Stream.WriteString(FName + ' ');
inherited SaveToDDL(Stream);
end;
//=== { TMetaUDFField } ======================================================
procedure TMetaUDFField.LoadFromQuery(QField, QCharset: TJvUIBStatement);
begin
inherited LoadFromQuery(QField, QCharset);
FPosition := QField.Fields.AsSmallint[6];
FMechanism := QField.Fields.AsSmallint[7];
FName := 'Field ' + IntToStr(FPosition);
end;
procedure TMetaUDFField.LoadFromStream(Stream: TStream);
begin
inherited LoadFromStream(Stream);
Stream.Read(FPosition, SizeOf(FPosition));
Stream.Read(FMechanism, SizeOf(FMechanism));
end;
class function TMetaUDFField.NodeType: TMetaNodeType;
begin
Result := MetaUDFField;
end;
procedure TMetaUDFField.SaveToDDLNode(Stream: TStringStream);
begin
if FFieldType = uftBlob then
Stream.WriteString('BLOB')
else
inherited SaveToDDLNode(Stream);
case FMechanism of
-1:
Stream.WriteString(' FREE_IT');
0:
Stream.WriteString(' BY VALUE');
1:
; // BY REFERENCE = default
2:
Stream.WriteString(' BY DESCRIPTOR');
end;
end;
procedure TMetaUDFField.SaveToStream(Stream: TStream);
begin
inherited SaveToStream(Stream);
Stream.Write(FPosition, SizeOf(FPosition));
Stream.Write(FMechanism, SizeOf(FMechanism));
end;
//=== { TMetaRole } ==========================================================
procedure TMetaRole.LoadFromQuery(QName: TJvUIBStatement);
begin
FName := Trim(QName.Fields.AsString[0]);
FOwner := QName.Fields.AsString[1];
end;
procedure TMetaRole.LoadFromStream(Stream: TStream);
begin
ReadString(Stream, FName);
ReadString(Stream, FOwner);
end;
class function TMetaRole.NodeClass: string;
begin
Result := 'Role';
end;
class function TMetaRole.NodeType: TMetaNodeType;
begin
Result := MetaRole;
end;
procedure TMetaRole.SaveToDDLNode(Stream: TStringStream);
begin
Stream.WriteString(Format('CREATE ROLE %s /* By user %s */', [FName, Trim(FOwner)]));
end;
procedure TMetaRole.SaveToStream(Stream: TStream);
begin
WriteString(Stream, FName);
WriteString(Stream, FOwner);
inherited SaveToStream(Stream);
end;
{$IFDEF USEJVCL}
{$IFDEF UNITVERSIONING}
initialization
RegisterUnitVersion(HInstance, UnitVersioning);
finalization
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
{$ENDIF USEJVCL}
end.